@electrolux-oss/plugin-infrawallet 0.1.0 → 0.1.3
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/README.md +24 -6
- package/dist/api/InfraWalletApi.esm.js.map +1 -1
- package/dist/api/InfraWalletApiClient.esm.js +12 -65
- package/dist/api/InfraWalletApiClient.esm.js.map +1 -1
- package/dist/api/functions.esm.js +34 -20
- package/dist/api/functions.esm.js.map +1 -1
- package/dist/components/ColumnsChartComponent/ColumnsChartComponent.esm.js +44 -7
- package/dist/components/ColumnsChartComponent/ColumnsChartComponent.esm.js.map +1 -1
- package/dist/components/CostReportsTableComponent/CostReportsTableComponent.esm.js +60 -15
- package/dist/components/CostReportsTableComponent/CostReportsTableComponent.esm.js.map +1 -1
- package/dist/components/InfraWalletIcon.esm.js +9 -0
- package/dist/components/InfraWalletIcon.esm.js.map +1 -0
- package/dist/components/PieChartComponent/PieChartComponent.esm.js +1 -1
- package/dist/components/PieChartComponent/PieChartComponent.esm.js.map +1 -1
- package/dist/components/ReportsComponent/ReportsComponent.esm.js +17 -12
- package/dist/components/ReportsComponent/ReportsComponent.esm.js.map +1 -1
- package/dist/components/TopbarComponent/TopbarComponent.esm.js +1 -11
- package/dist/components/TopbarComponent/TopbarComponent.esm.js.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.esm.js +1 -0
- package/dist/index.esm.js.map +1 -1
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
- Swift response times with cached cost data, ensuring rapid access to financial insights fetched from cloud platforms
|
|
12
12
|
- Easy configuration and deployment as a Backstage plugin, both frontend and backend plugins are production-ready
|
|
13
13
|
|
|
14
|
-
\*
|
|
14
|
+
\*_The latest version supports AWS, Azure and GCP cost aggregation while the framework is designed to be extensible to support others. Feel free to contribute to the project._
|
|
15
15
|
|
|
16
16
|
## Getting started
|
|
17
17
|
|
|
@@ -67,6 +67,24 @@ backend:
|
|
|
67
67
|
clientSecret: <Client_secret_of_the_created_application>
|
|
68
68
|
```
|
|
69
69
|
|
|
70
|
+
#### GCP
|
|
71
|
+
|
|
72
|
+
InfraWallet relies on GCP Big Query to fetch cost data. This means that the billing data needs to be exported to a big query dataset, and a service account needs to be created for InfraWallet. The steps of exporting billing data to Big Query can be found [here](https://cloud.google.com/billing/docs/how-to/export-data-bigquery). Then, visit Google Cloud Console and navigate to the `IAM & Admin` section in the billing account. Click `Service Accounts`, and create a new service account. The service account needs to have `BigQuery Data Viewer` and `BigQuery Job User` roles. On the `Service Accounts` page, click the three dots (menu) in the `Actions` column for the newly created service account and select `Manage keys`. There click `Add key` -> `Create new key`, and use `JSON` as the format. Download the JSON key file and keep it safe.
|
|
73
|
+
|
|
74
|
+
After setting up the resources above, add the following configurations in `app-config.yaml`:
|
|
75
|
+
|
|
76
|
+
```yaml
|
|
77
|
+
backend:
|
|
78
|
+
infraWallet:
|
|
79
|
+
integrations:
|
|
80
|
+
gcp:
|
|
81
|
+
- name: <unique_name_of_this_account>
|
|
82
|
+
keyFilePath: <path_to_your_json_key_file> # if you run it in a k8s pod, you may need to create a secret and mount it to the pod
|
|
83
|
+
projectId: <GCP_project_that_your_big_query_dataset_belongs_to>
|
|
84
|
+
datasetId: <big_query_dataset_id>
|
|
85
|
+
tableId: <big_query_table_id>
|
|
86
|
+
```
|
|
87
|
+
|
|
70
88
|
### Adjust Category Mappings if Needed
|
|
71
89
|
|
|
72
90
|
The category mappings are stored in the plugin's database. If there is no mapping found in the DB when initializing the plugin, the default mappings will be used. The default mappings can be found in the [plugins/infrawallet-backend/seeds/init.js](plugins/infrawallet-backend/seeds/init.js) file. You can adjust this seed file to fit your needs, or update the database directly later on.
|
|
@@ -149,13 +167,13 @@ modify `packages/app/src/App.tsx` and add the following code
|
|
|
149
167
|
|
|
150
168
|
```ts
|
|
151
169
|
...
|
|
152
|
-
import
|
|
170
|
+
import { InfraWalletIcon } from '@electrolux-oss/plugin-infrawallet';
|
|
153
171
|
...
|
|
154
172
|
<Sidebar>
|
|
155
173
|
...
|
|
156
174
|
<SidebarGroup label="Menu" icon={<MenuIcon />}>
|
|
157
175
|
<SidebarItem
|
|
158
|
-
icon={
|
|
176
|
+
icon={InfraWalletIcon}
|
|
159
177
|
to="infrawallet"
|
|
160
178
|
text="InfraWallet"
|
|
161
179
|
/>
|
|
@@ -186,7 +204,7 @@ export default async function createPlugin(
|
|
|
186
204
|
return await createRouter({
|
|
187
205
|
logger: env.logger,
|
|
188
206
|
config: env.config,
|
|
189
|
-
|
|
207
|
+
cache: env.cache.getClient(),
|
|
190
208
|
database: env.database,
|
|
191
209
|
});
|
|
192
210
|
}
|
|
@@ -209,9 +227,9 @@ async function main() {
|
|
|
209
227
|
|
|
210
228
|
## Local Development
|
|
211
229
|
|
|
212
|
-
Your plugin has been added to the example app in this repository, meaning you'll be able to access it by running `yarn
|
|
230
|
+
First of all, make sure you are using either Node 18 or Node 20 for this project. Your plugin has been added to the example app in this repository, meaning you'll be able to access it by running `yarn install && yarn dev` in the root directory, and then navigating to [/infrawallet](http://localhost:3000/infrawallet).
|
|
213
231
|
|
|
214
|
-
You can also serve the plugin in isolation by running `yarn start` in the plugin directory.
|
|
232
|
+
You can also serve the plugin in isolation by running `yarn install && yarn start` in the plugin directory.
|
|
215
233
|
This method of serving the plugin provides quicker iteration speed and a faster startup and hot reloads.
|
|
216
234
|
It is only meant for local development, and the setup for it can be found inside the [/dev](./dev) directory.
|
|
217
235
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InfraWalletApi.esm.js","sources":["../../src/api/InfraWalletApi.ts"],"sourcesContent":["import { createApiRef } from '@backstage/core-plugin-api';\nimport { CostReportsResponse } from './types';\nimport { Response } from 'node-fetch';\n\n/** @public */\nexport const infraWalletApiRef = createApiRef<InfraWalletApi>({\n id: 'plugin.infrawallet',\n});\n\n/** @public */\nexport interface InfraWalletApi {\n get(path: string
|
|
1
|
+
{"version":3,"file":"InfraWalletApi.esm.js","sources":["../../src/api/InfraWalletApi.ts"],"sourcesContent":["import { createApiRef } from '@backstage/core-plugin-api';\nimport { CostReportsResponse } from './types';\nimport { Response } from 'node-fetch';\n\n/** @public */\nexport const infraWalletApiRef = createApiRef<InfraWalletApi>({\n id: 'plugin.infrawallet',\n});\n\n/** @public */\nexport interface InfraWalletApi {\n get(path: string): Promise<Response>;\n getCostReports(\n filters: string,\n groups: string,\n granularity: string,\n startTime: Date,\n endTime: Date,\n ): Promise<CostReportsResponse>;\n}\n"],"names":[],"mappings":";;AAKO,MAAM,oBAAoB,YAA6B,CAAA;AAAA,EAC5D,EAAI,EAAA,oBAAA;AACN,CAAC;;;;"}
|
|
@@ -13,75 +13,22 @@ class InfraWalletApiClient {
|
|
|
13
13
|
this.identityApi = options.identityApi;
|
|
14
14
|
this.backendUrl = options.configApi.getString("backend.baseUrl");
|
|
15
15
|
}
|
|
16
|
-
async get(path
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
`${this.backendUrl}/${path}`,
|
|
27
|
-
hdrs,
|
|
28
|
-
method,
|
|
29
|
-
data
|
|
30
|
-
);
|
|
31
|
-
}
|
|
32
|
-
async put(path, headers, data) {
|
|
33
|
-
const hdrs = {
|
|
34
|
-
...headers,
|
|
35
|
-
"Content-Type": "application/json"
|
|
36
|
-
};
|
|
37
|
-
const method = "PUT";
|
|
38
|
-
return await this.requestRaw(
|
|
39
|
-
`${this.backendUrl}/${path}`,
|
|
40
|
-
hdrs,
|
|
41
|
-
method,
|
|
42
|
-
data
|
|
43
|
-
);
|
|
44
|
-
}
|
|
45
|
-
async delete(path, headers, data) {
|
|
46
|
-
const hdrs = {
|
|
47
|
-
...headers,
|
|
48
|
-
"Content-Type": "application/json"
|
|
49
|
-
};
|
|
50
|
-
const method = "DELETE";
|
|
51
|
-
return await this.requestRaw(
|
|
52
|
-
`${this.backendUrl}/${path}`,
|
|
53
|
-
hdrs,
|
|
54
|
-
method,
|
|
55
|
-
data
|
|
56
|
-
);
|
|
57
|
-
}
|
|
58
|
-
async requestRaw(url, headers, method, data) {
|
|
59
|
-
let payload;
|
|
60
|
-
if (!method) {
|
|
61
|
-
payload = {
|
|
62
|
-
method: "GET",
|
|
63
|
-
headers
|
|
64
|
-
};
|
|
65
|
-
} else {
|
|
66
|
-
payload = {
|
|
67
|
-
method,
|
|
68
|
-
headers,
|
|
69
|
-
body: JSON.stringify(data)
|
|
70
|
-
};
|
|
16
|
+
async get(path) {
|
|
17
|
+
const url = `${this.backendUrl}/${path}`;
|
|
18
|
+
const { token: idToken } = await this.identityApi.getCredentials();
|
|
19
|
+
const response = await fetch(url, {
|
|
20
|
+
headers: idToken ? { Authorization: `Bearer ${idToken}` } : {}
|
|
21
|
+
});
|
|
22
|
+
if (!response.ok) {
|
|
23
|
+
const payload = await response.text();
|
|
24
|
+
const message = `Request failed with ${response.status} ${response.statusText}, ${payload}`;
|
|
25
|
+
throw new Error(message);
|
|
71
26
|
}
|
|
72
|
-
return await
|
|
27
|
+
return await response.json();
|
|
73
28
|
}
|
|
74
29
|
async getCostReports(filters, groups, granularity, startTime, endTime) {
|
|
75
|
-
const { token: idToken } = await this.identityApi.getCredentials();
|
|
76
|
-
const headers = idToken ? { Authorization: `Bearer ${idToken}` } : {};
|
|
77
30
|
const url = `api/infrawallet/reports?&filters=${filters}&groups=${groups}&granularity=${granularity}&startTime=${startTime.getTime()}&endTime=${endTime.getTime()}`;
|
|
78
|
-
|
|
79
|
-
if (!response.ok) {
|
|
80
|
-
const r = await response.json();
|
|
81
|
-
throw new Error(r.error.message);
|
|
82
|
-
} else {
|
|
83
|
-
return await response.json();
|
|
84
|
-
}
|
|
31
|
+
return await this.get(url);
|
|
85
32
|
}
|
|
86
33
|
}
|
|
87
34
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InfraWalletApiClient.esm.js","sources":["../../src/api/InfraWalletApiClient.ts"],"sourcesContent":["import { ConfigApi, IdentityApi } from '@backstage/core-plugin-api';\nimport fetch
|
|
1
|
+
{"version":3,"file":"InfraWalletApiClient.esm.js","sources":["../../src/api/InfraWalletApiClient.ts"],"sourcesContent":["import { ConfigApi, IdentityApi } from '@backstage/core-plugin-api';\nimport fetch from 'node-fetch';\nimport { InfraWalletApi } from './InfraWalletApi';\nimport { CostReportsResponse } from './types';\n\n/** @public */\nexport class InfraWalletApiClient implements InfraWalletApi {\n private readonly identityApi: IdentityApi;\n private readonly backendUrl: string;\n\n constructor(options: { identityApi: IdentityApi; configApi: ConfigApi }) {\n this.identityApi = options.identityApi;\n this.backendUrl = options.configApi.getString('backend.baseUrl');\n }\n\n async get(path: string): Promise<any> {\n const url = `${this.backendUrl}/${path}`;\n const { token: idToken } = await this.identityApi.getCredentials();\n const response = await fetch(url, {\n headers: idToken ? { Authorization: `Bearer ${idToken}` } : {},\n });\n\n if (!response.ok) {\n const payload = await response.text();\n const message = `Request failed with ${response.status} ${response.statusText}, ${payload}`;\n throw new Error(message);\n }\n\n return await response.json();\n }\n\n async getCostReports(\n filters: string,\n groups: string,\n granularity: string,\n startTime: Date,\n endTime: Date,\n ): Promise<CostReportsResponse> {\n const url = `api/infrawallet/reports?&filters=${filters}&groups=${groups}&granularity=${granularity}&startTime=${startTime.getTime()}&endTime=${endTime.getTime()}`;\n return await this.get(url);\n }\n}\n"],"names":[],"mappings":";;;;;;;;AAMO,MAAM,oBAA+C,CAAA;AAAA,EAI1D,YAAY,OAA6D,EAAA;AAHzE,IAAiB,aAAA,CAAA,IAAA,EAAA,aAAA,CAAA,CAAA;AACjB,IAAiB,aAAA,CAAA,IAAA,EAAA,YAAA,CAAA,CAAA;AAGf,IAAA,IAAA,CAAK,cAAc,OAAQ,CAAA,WAAA,CAAA;AAC3B,IAAA,IAAA,CAAK,UAAa,GAAA,OAAA,CAAQ,SAAU,CAAA,SAAA,CAAU,iBAAiB,CAAA,CAAA;AAAA,GACjE;AAAA,EAEA,MAAM,IAAI,IAA4B,EAAA;AACpC,IAAA,MAAM,GAAM,GAAA,CAAA,EAAG,IAAK,CAAA,UAAU,IAAI,IAAI,CAAA,CAAA,CAAA;AACtC,IAAA,MAAM,EAAE,KAAO,EAAA,OAAA,KAAY,MAAM,IAAA,CAAK,YAAY,cAAe,EAAA,CAAA;AACjE,IAAM,MAAA,QAAA,GAAW,MAAM,KAAA,CAAM,GAAK,EAAA;AAAA,MAChC,OAAA,EAAS,UAAU,EAAE,aAAA,EAAe,UAAU,OAAO,CAAA,CAAA,KAAO,EAAC;AAAA,KAC9D,CAAA,CAAA;AAED,IAAI,IAAA,CAAC,SAAS,EAAI,EAAA;AAChB,MAAM,MAAA,OAAA,GAAU,MAAM,QAAA,CAAS,IAAK,EAAA,CAAA;AACpC,MAAM,MAAA,OAAA,GAAU,uBAAuB,QAAS,CAAA,MAAM,IAAI,QAAS,CAAA,UAAU,KAAK,OAAO,CAAA,CAAA,CAAA;AACzF,MAAM,MAAA,IAAI,MAAM,OAAO,CAAA,CAAA;AAAA,KACzB;AAEA,IAAO,OAAA,MAAM,SAAS,IAAK,EAAA,CAAA;AAAA,GAC7B;AAAA,EAEA,MAAM,cACJ,CAAA,OAAA,EACA,MACA,EAAA,WAAA,EACA,WACA,OAC8B,EAAA;AAC9B,IAAA,MAAM,GAAM,GAAA,CAAA,iCAAA,EAAoC,OAAO,CAAA,QAAA,EAAW,MAAM,CAAgB,aAAA,EAAA,WAAW,CAAc,WAAA,EAAA,SAAA,CAAU,OAAQ,EAAC,CAAY,SAAA,EAAA,OAAA,CAAQ,SAAS,CAAA,CAAA,CAAA;AACjK,IAAO,OAAA,MAAM,IAAK,CAAA,GAAA,CAAI,GAAG,CAAA,CAAA;AAAA,GAC3B;AACF;;;;"}
|
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
import { reduce } from 'lodash';
|
|
2
1
|
import { parse, subMonths, format } from 'date-fns';
|
|
2
|
+
import { reduce } from 'lodash';
|
|
3
|
+
import moment from 'moment';
|
|
3
4
|
|
|
4
5
|
const mergeCostReports = (reports, threshold) => {
|
|
5
|
-
if (reports.length <= threshold) {
|
|
6
|
-
return reports;
|
|
7
|
-
}
|
|
8
6
|
const totalCosts = [];
|
|
9
7
|
reports.forEach((report) => {
|
|
10
8
|
let total = 0;
|
|
@@ -17,25 +15,25 @@ const mergeCostReports = (reports, threshold) => {
|
|
|
17
15
|
const idsToBeKept = sortedTotalCosts.slice(0, threshold).map((v) => v.id);
|
|
18
16
|
const mergedReports = reduce(
|
|
19
17
|
reports,
|
|
20
|
-
(
|
|
18
|
+
(accumulator, report) => {
|
|
21
19
|
let keyName = "others";
|
|
22
20
|
if (idsToBeKept.includes(report.id)) {
|
|
23
21
|
keyName = report.id;
|
|
24
22
|
}
|
|
25
|
-
if (!
|
|
26
|
-
|
|
23
|
+
if (!accumulator[keyName]) {
|
|
24
|
+
accumulator[keyName] = {
|
|
27
25
|
id: keyName,
|
|
28
26
|
reports: {}
|
|
29
27
|
};
|
|
30
28
|
}
|
|
31
29
|
Object.keys(report.reports).forEach((key) => {
|
|
32
|
-
if (
|
|
33
|
-
|
|
30
|
+
if (accumulator[keyName].reports[key]) {
|
|
31
|
+
accumulator[keyName].reports[key] += report.reports[key];
|
|
34
32
|
} else {
|
|
35
|
-
|
|
33
|
+
accumulator[keyName].reports[key] = report.reports[key];
|
|
36
34
|
}
|
|
37
35
|
});
|
|
38
|
-
return
|
|
36
|
+
return accumulator;
|
|
39
37
|
},
|
|
40
38
|
{}
|
|
41
39
|
);
|
|
@@ -44,28 +42,30 @@ const mergeCostReports = (reports, threshold) => {
|
|
|
44
42
|
const aggregateCostReports = (reports, aggregatedBy) => {
|
|
45
43
|
const aggregatedReports = reduce(
|
|
46
44
|
reports,
|
|
47
|
-
(
|
|
45
|
+
(accumulator, report) => {
|
|
48
46
|
let keyName = "no value";
|
|
49
47
|
if (aggregatedBy && aggregatedBy in report) {
|
|
50
48
|
keyName = report[aggregatedBy];
|
|
51
49
|
} else if (aggregatedBy === "none") {
|
|
52
50
|
keyName = "Total cloud costs";
|
|
53
51
|
}
|
|
54
|
-
if (!
|
|
55
|
-
|
|
52
|
+
if (!accumulator[keyName]) {
|
|
53
|
+
accumulator[keyName] = {
|
|
56
54
|
id: keyName,
|
|
57
55
|
reports: {}
|
|
58
56
|
};
|
|
59
|
-
|
|
57
|
+
if (aggregatedBy !== void 0) {
|
|
58
|
+
accumulator[keyName][aggregatedBy] = keyName;
|
|
59
|
+
}
|
|
60
60
|
}
|
|
61
61
|
Object.keys(report.reports).forEach((key) => {
|
|
62
|
-
if (
|
|
63
|
-
|
|
62
|
+
if (accumulator[keyName].reports[key]) {
|
|
63
|
+
accumulator[keyName].reports[key] += report.reports[key];
|
|
64
64
|
} else {
|
|
65
|
-
|
|
65
|
+
accumulator[keyName].reports[key] = report.reports[key];
|
|
66
66
|
}
|
|
67
67
|
});
|
|
68
|
-
return
|
|
68
|
+
return accumulator;
|
|
69
69
|
},
|
|
70
70
|
{}
|
|
71
71
|
);
|
|
@@ -95,6 +95,20 @@ const getPreviousMonth = (month) => {
|
|
|
95
95
|
const previousMonth = subMonths(date, 1);
|
|
96
96
|
return format(previousMonth, "yyyy-MM");
|
|
97
97
|
};
|
|
98
|
+
const getPeriodStrings = (granularity, startTime, endTime) => {
|
|
99
|
+
const result = [];
|
|
100
|
+
const current = moment(startTime);
|
|
101
|
+
while (current.isSameOrBefore(endTime) && current.isSameOrBefore(moment())) {
|
|
102
|
+
if (granularity === "monthly") {
|
|
103
|
+
result.push(current.format("YYYY-MM"));
|
|
104
|
+
current.add(1, "months");
|
|
105
|
+
} else {
|
|
106
|
+
result.push(current.format("YYYY-MM-DD"));
|
|
107
|
+
current.add(1, "days");
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return result;
|
|
111
|
+
};
|
|
98
112
|
|
|
99
|
-
export { aggregateCostReports, getAllReportTags, getPreviousMonth, mergeCostReports };
|
|
113
|
+
export { aggregateCostReports, getAllReportTags, getPeriodStrings, getPreviousMonth, mergeCostReports };
|
|
100
114
|
//# sourceMappingURL=functions.esm.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"functions.esm.js","sources":["../../src/api/functions.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"functions.esm.js","sources":["../../src/api/functions.ts"],"sourcesContent":["import { format, parse, subMonths } from 'date-fns';\nimport { reduce } from 'lodash';\nimport moment from 'moment';\nimport { Report } from './types';\n\nexport const mergeCostReports = (\n reports: Report[],\n threshold: number,\n): Report[] => {\n const totalCosts: { id: string; total: number }[] = [];\n reports.forEach(report => {\n let total = 0;\n Object.values(report.reports).forEach(v => {\n total += v as number;\n });\n totalCosts.push({ id: report.id, total: total });\n });\n const sortedTotalCosts = totalCosts.sort((a, b) => b.total - a.total);\n const idsToBeKept = sortedTotalCosts.slice(0, threshold).map(v => v.id);\n\n const mergedReports = reduce(\n reports,\n (accumulator: { [key: string]: Report }, report) => {\n let keyName = 'others';\n if (idsToBeKept.includes(report.id)) {\n keyName = report.id;\n }\n if (!accumulator[keyName]) {\n accumulator[keyName] = {\n id: keyName,\n reports: {},\n };\n }\n\n Object.keys(report.reports).forEach(key => {\n if (accumulator[keyName].reports[key]) {\n accumulator[keyName].reports[key] += report.reports[key];\n } else {\n accumulator[keyName].reports[key] = report.reports[key];\n }\n });\n return accumulator;\n },\n {},\n );\n\n return Object.values(mergedReports);\n};\n\nexport const aggregateCostReports = (\n reports: Report[],\n aggregatedBy?: string,\n): Report[] => {\n const aggregatedReports: { [key: string]: Report } = reduce(\n reports,\n (accumulator, report) => {\n let keyName: string = 'no value';\n if (aggregatedBy && aggregatedBy in report) {\n keyName = report[aggregatedBy] as string;\n } else if (aggregatedBy === 'none') {\n keyName = 'Total cloud costs';\n }\n\n if (!accumulator[keyName]) {\n accumulator[keyName] = {\n id: keyName,\n reports: {},\n } as {\n id: string;\n reports: { [key: string]: number };\n [key: string]: any;\n };\n\n if (aggregatedBy !== undefined) {\n accumulator[keyName][aggregatedBy] = keyName;\n }\n }\n\n Object.keys(report.reports).forEach(key => {\n if (accumulator[keyName].reports[key]) {\n accumulator[keyName].reports[key] += report.reports[key];\n } else {\n accumulator[keyName].reports[key] = report.reports[key];\n }\n });\n return accumulator;\n },\n {} as { [key: string]: Report },\n );\n return Object.values(aggregatedReports);\n};\n\nexport const getAllReportTags = (reports: Report[]): string[] => {\n const tags = new Set<string>();\n const reservedKeys = [\n 'id',\n 'name',\n 'service',\n 'category',\n 'provider',\n 'reports',\n ];\n reports.forEach(report => {\n Object.keys(report).forEach(key => {\n if (reservedKeys.indexOf(key) === -1) {\n tags.add(key);\n }\n });\n });\n return Array.from(tags);\n};\n\nexport const getPreviousMonth = (month: string): string => {\n const date = parse(month, 'yyyy-MM', new Date());\n const previousMonth = subMonths(date, 1);\n return format(previousMonth, 'yyyy-MM');\n};\n\nexport const getPeriodStrings = (\n granularity: string,\n startTime: Date,\n endTime: Date,\n): string[] => {\n const result: string[] = [];\n const current = moment(startTime);\n\n while (current.isSameOrBefore(endTime) && current.isSameOrBefore(moment())) {\n if (granularity === 'monthly') {\n result.push(current.format('YYYY-MM'));\n current.add(1, 'months');\n } else {\n result.push(current.format('YYYY-MM-DD'));\n current.add(1, 'days');\n }\n }\n\n return result;\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -1,10 +1,44 @@
|
|
|
1
|
-
import { Paper } from '@material-ui/core';
|
|
2
|
-
import { useTheme, makeStyles } from '@material-ui/core/styles';
|
|
1
|
+
import { Switch, Paper, Grid } from '@material-ui/core';
|
|
2
|
+
import { withStyles, useTheme, makeStyles } from '@material-ui/core/styles';
|
|
3
3
|
import humanFormat from 'human-format';
|
|
4
4
|
import React from 'react';
|
|
5
5
|
import Chart from 'react-apexcharts';
|
|
6
6
|
|
|
7
|
+
const Toggle = withStyles((theme) => ({
|
|
8
|
+
root: {
|
|
9
|
+
width: 28,
|
|
10
|
+
height: 16,
|
|
11
|
+
padding: 0,
|
|
12
|
+
display: "flex"
|
|
13
|
+
},
|
|
14
|
+
switchBase: {
|
|
15
|
+
padding: 2,
|
|
16
|
+
color: theme.palette.grey[500],
|
|
17
|
+
"&$checked": {
|
|
18
|
+
transform: "translateX(12px)",
|
|
19
|
+
color: theme.palette.common.white,
|
|
20
|
+
"& + $track": {
|
|
21
|
+
opacity: 1,
|
|
22
|
+
backgroundColor: theme.palette.primary.main,
|
|
23
|
+
borderColor: theme.palette.primary.main
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
thumb: {
|
|
28
|
+
width: 12,
|
|
29
|
+
height: 12,
|
|
30
|
+
boxShadow: "none"
|
|
31
|
+
},
|
|
32
|
+
track: {
|
|
33
|
+
border: `1px solid ${theme.palette.grey[500]}`,
|
|
34
|
+
borderRadius: 16 / 2,
|
|
35
|
+
opacity: 1,
|
|
36
|
+
backgroundColor: theme.palette.common.white
|
|
37
|
+
},
|
|
38
|
+
checked: {}
|
|
39
|
+
}))(Switch);
|
|
7
40
|
const ColumnsChartComponent = ({
|
|
41
|
+
granularitySetter,
|
|
8
42
|
categories,
|
|
9
43
|
series,
|
|
10
44
|
height,
|
|
@@ -62,7 +96,7 @@ const ColumnsChartComponent = ({
|
|
|
62
96
|
},
|
|
63
97
|
stacked: true,
|
|
64
98
|
toolbar: {
|
|
65
|
-
show:
|
|
99
|
+
show: false
|
|
66
100
|
},
|
|
67
101
|
events: {
|
|
68
102
|
dataPointSelection: dataPointSelectionHandler
|
|
@@ -75,14 +109,16 @@ const ColumnsChartComponent = ({
|
|
|
75
109
|
decimalsInFloat: 2
|
|
76
110
|
},
|
|
77
111
|
dataLabels: {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
112
|
+
enabled: false
|
|
113
|
+
},
|
|
114
|
+
tooltip: {
|
|
115
|
+
y: {
|
|
116
|
+
formatter: (value) => {
|
|
117
|
+
return `$${humanFormat(value, {
|
|
81
118
|
scale: customScale,
|
|
82
119
|
separator: ""
|
|
83
120
|
})}`;
|
|
84
121
|
}
|
|
85
|
-
return "null";
|
|
86
122
|
}
|
|
87
123
|
},
|
|
88
124
|
legend: {
|
|
@@ -152,6 +188,7 @@ const ColumnsChartComponent = ({
|
|
|
152
188
|
{
|
|
153
189
|
className: thumbnail ? classes.thumbnailPaper : classes.fixedHeightPaper
|
|
154
190
|
},
|
|
191
|
+
/* @__PURE__ */ React.createElement(Grid, { container: true, justifyContent: "flex-end", spacing: 1 }, /* @__PURE__ */ React.createElement(Grid, { item: true }, "Monthly"), /* @__PURE__ */ React.createElement(Grid, { item: true }, /* @__PURE__ */ React.createElement(Toggle, { onChange: (event) => granularitySetter(event.target.checked ? "daily" : "monthly") })), /* @__PURE__ */ React.createElement(Grid, { item: true }, "Daily")),
|
|
155
192
|
/* @__PURE__ */ React.createElement(
|
|
156
193
|
Chart,
|
|
157
194
|
{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ColumnsChartComponent.esm.js","sources":["../../../src/components/ColumnsChartComponent/ColumnsChartComponent.tsx"],"sourcesContent":["import { Paper } from '@material-ui/core';\nimport { makeStyles, useTheme } from '@material-ui/core/styles';\nimport humanFormat from 'human-format';\nimport React, { FC } from 'react';\nimport Chart from 'react-apexcharts';\nimport { ColumnsChartComponentProps } from '../types';\n\nexport const ColumnsChartComponent: FC<ColumnsChartComponentProps> = ({\n categories,\n series,\n height,\n thumbnail,\n dataPointSelectionHandler,\n}) => {\n const defaultTheme = useTheme();\n const useStyles = makeStyles({\n fixedHeightPaper: {\n padding: '16px',\n display: 'flex',\n overflow: 'auto',\n flexDirection: 'column',\n height: height ? height : 300,\n },\n thumbnailPaper: {\n display: 'flex',\n overflow: 'auto',\n flexDirection: 'column',\n height: height ? height - 50 : 100,\n },\n });\n const classes = useStyles();\n const customScale = humanFormat.Scale.create(['', 'K', 'M', 'B'], 1000);\n\n const state = thumbnail\n ? {\n
|
|
1
|
+
{"version":3,"file":"ColumnsChartComponent.esm.js","sources":["../../../src/components/ColumnsChartComponent/ColumnsChartComponent.tsx"],"sourcesContent":["import { Grid, Paper, Switch } from '@material-ui/core';\nimport { withStyles, makeStyles, useTheme } from '@material-ui/core/styles';\nimport humanFormat from 'human-format';\nimport React, { FC } from 'react';\nimport Chart from 'react-apexcharts';\nimport { ColumnsChartComponentProps } from '../types';\n\nconst Toggle = withStyles((theme) => ({\n root: {\n width: 28,\n height: 16,\n padding: 0,\n display: 'flex',\n },\n switchBase: {\n padding: 2,\n color: theme.palette.grey[500],\n '&$checked': {\n transform: 'translateX(12px)',\n color: theme.palette.common.white,\n '& + $track': {\n opacity: 1,\n backgroundColor: theme.palette.primary.main,\n borderColor: theme.palette.primary.main,\n },\n },\n },\n thumb: {\n width: 12,\n height: 12,\n boxShadow: 'none',\n },\n track: {\n border: `1px solid ${theme.palette.grey[500]}`,\n borderRadius: 16 / 2,\n opacity: 1,\n backgroundColor: theme.palette.common.white,\n },\n checked: {},\n}))(Switch);\n\nexport const ColumnsChartComponent: FC<ColumnsChartComponentProps> = ({\n granularitySetter,\n categories,\n series,\n height,\n thumbnail,\n dataPointSelectionHandler,\n}) => {\n const defaultTheme = useTheme();\n const useStyles = makeStyles({\n fixedHeightPaper: {\n padding: '16px',\n display: 'flex',\n overflow: 'auto',\n flexDirection: 'column',\n height: height ? height : 300,\n },\n thumbnailPaper: {\n display: 'flex',\n overflow: 'auto',\n flexDirection: 'column',\n height: height ? height - 50 : 100,\n },\n });\n const classes = useStyles();\n const customScale = humanFormat.Scale.create(['', 'K', 'M', 'B'], 1000);\n\n const state = thumbnail\n ? {\n options: {\n chart: {\n animations: {\n enabled: false,\n },\n zoom: {\n enabled: false,\n },\n stacked: true,\n toolbar: {\n show: false,\n },\n sparkline: {\n enabled: true,\n },\n },\n xaxis: {\n categories: categories,\n },\n theme: {\n mode: defaultTheme.palette.type,\n },\n },\n series: series,\n }\n : {\n options: {\n chart: {\n animations: {\n enabled: false,\n },\n stacked: true,\n toolbar: {\n show: false,\n },\n events: {\n dataPointSelection: dataPointSelectionHandler,\n },\n },\n xaxis: {\n categories: categories,\n },\n yaxis: {\n decimalsInFloat: 2,\n },\n dataLabels: {\n enabled: false,\n },\n tooltip: {\n y: {\n formatter: (value: number) => {\n return `$${humanFormat(value, {\n scale: customScale,\n separator: '',\n })}`;\n },\n },\n },\n legend: {\n showForSingleSeries: true,\n },\n theme: {\n mode: defaultTheme.palette.type,\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\n className={thumbnail ? classes.thumbnailPaper : classes.fixedHeightPaper}\n >\n <Grid container justifyContent=\"flex-end\" spacing={1}>\n <Grid item>Monthly</Grid>\n <Grid item>\n <Toggle onChange={event => granularitySetter(event.target.checked ? 'daily' : 'monthly')} />\n </Grid>\n <Grid item>Daily</Grid>\n </Grid>\n <Chart\n options={state.options}\n series={state.series}\n type=\"bar\"\n height={height ? height - 50 : 250}\n />\n </Paper>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -1,27 +1,40 @@
|
|
|
1
|
+
import Chip from '@material-ui/core/Chip';
|
|
1
2
|
import Typography from '@material-ui/core/Typography';
|
|
2
3
|
import { makeStyles } from '@material-ui/core/styles';
|
|
3
4
|
import Box from '@mui/material/Box';
|
|
4
|
-
import { DataGrid } from '@mui/x-data-grid';
|
|
5
|
+
import { DataGrid, GridToolbarContainer, GridToolbarExport } from '@mui/x-data-grid';
|
|
5
6
|
import humanFormat from 'human-format';
|
|
6
7
|
import React from 'react';
|
|
7
8
|
import { getPreviousMonth } from '../../api/functions.esm.js';
|
|
8
9
|
import { TrendBarComponent } from './TrendBarComponent.esm.js';
|
|
9
10
|
|
|
10
|
-
const useStyles = makeStyles({
|
|
11
|
+
const useStyles = makeStyles((theme) => ({
|
|
11
12
|
increase: {
|
|
12
13
|
color: "red"
|
|
13
14
|
},
|
|
14
15
|
decrease: {
|
|
15
16
|
color: "green"
|
|
17
|
+
},
|
|
18
|
+
container: {
|
|
19
|
+
display: "flex",
|
|
20
|
+
alignItems: "center"
|
|
21
|
+
},
|
|
22
|
+
clip: {
|
|
23
|
+
backgroundColor: "#deebff",
|
|
24
|
+
color: "#0052cc",
|
|
25
|
+
marginLeft: theme.spacing(1)
|
|
16
26
|
}
|
|
17
|
-
});
|
|
27
|
+
}));
|
|
28
|
+
function CustomToolbar() {
|
|
29
|
+
return /* @__PURE__ */ React.createElement(GridToolbarContainer, null, /* @__PURE__ */ React.createElement(GridToolbarExport, { printOptions: { disableToolbarButton: true } }));
|
|
30
|
+
}
|
|
18
31
|
const CostReportsTableComponent = ({
|
|
19
32
|
reports,
|
|
20
|
-
aggregatedBy
|
|
33
|
+
aggregatedBy,
|
|
34
|
+
periods
|
|
21
35
|
}) => {
|
|
22
36
|
const classes = useStyles();
|
|
23
37
|
const customScale = humanFormat.Scale.create(["", "K", "M", "B"], 1e3);
|
|
24
|
-
const periods = Object.keys(reports[0].reports);
|
|
25
38
|
const columns = [
|
|
26
39
|
{
|
|
27
40
|
field: aggregatedBy,
|
|
@@ -29,13 +42,32 @@ const CostReportsTableComponent = ({
|
|
|
29
42
|
minWidth: 200,
|
|
30
43
|
flex: 2,
|
|
31
44
|
renderCell: (params) => {
|
|
32
|
-
|
|
45
|
+
let formattedValue = params.formattedValue;
|
|
46
|
+
let chipLabel = null;
|
|
47
|
+
if (aggregatedBy === "service" || aggregatedBy === "name") {
|
|
48
|
+
if (params.formattedValue !== void 0 && params.formattedValue.indexOf("/") !== -1) {
|
|
49
|
+
const splitValue = params.formattedValue.split("/");
|
|
50
|
+
formattedValue = splitValue[1];
|
|
51
|
+
chipLabel = splitValue[0].toLowerCase();
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return /* @__PURE__ */ React.createElement(
|
|
55
|
+
Typography,
|
|
56
|
+
{
|
|
57
|
+
variant: "body2",
|
|
58
|
+
component: "div",
|
|
59
|
+
className: classes.container
|
|
60
|
+
},
|
|
61
|
+
formattedValue,
|
|
62
|
+
chipLabel && /* @__PURE__ */ React.createElement(Chip, { size: "small", label: chipLabel, className: classes.clip })
|
|
63
|
+
);
|
|
33
64
|
}
|
|
34
65
|
},
|
|
35
66
|
{
|
|
36
67
|
field: "TREND",
|
|
37
68
|
headerName: "TREND",
|
|
38
69
|
width: 100,
|
|
70
|
+
disableExport: true,
|
|
39
71
|
renderCell: (params) => {
|
|
40
72
|
return /* @__PURE__ */ React.createElement(
|
|
41
73
|
TrendBarComponent,
|
|
@@ -66,16 +98,21 @@ const CostReportsTableComponent = ({
|
|
|
66
98
|
},
|
|
67
99
|
valueFormatter: (value, row, column) => {
|
|
68
100
|
if (typeof value === "number") {
|
|
69
|
-
const previousPeriod = getPreviousMonth(column.field);
|
|
101
|
+
const previousPeriod = period.length === 7 ? getPreviousMonth(column.field) : "";
|
|
70
102
|
const formattedValue = humanFormat(value, {
|
|
71
103
|
scale: customScale,
|
|
72
|
-
separator: ""
|
|
104
|
+
separator: "",
|
|
105
|
+
decimals: 2
|
|
73
106
|
});
|
|
74
|
-
if (previousPeriod
|
|
107
|
+
if (periods.includes(previousPeriod) && row.reports[previousPeriod] > 0) {
|
|
75
108
|
const diff = row.reports[column.field] - row.reports[previousPeriod];
|
|
76
|
-
const percentage =
|
|
109
|
+
const percentage = Math.round(
|
|
110
|
+
diff / row.reports[previousPeriod] * 100
|
|
111
|
+
);
|
|
77
112
|
const mark = diff > 0 ? "+" : "";
|
|
78
|
-
|
|
113
|
+
if (percentage >= 1 || percentage <= -1) {
|
|
114
|
+
return `$${formattedValue} (${mark}${percentage}%)`;
|
|
115
|
+
}
|
|
79
116
|
}
|
|
80
117
|
return `$${formattedValue}`;
|
|
81
118
|
}
|
|
@@ -85,11 +122,13 @@ const CostReportsTableComponent = ({
|
|
|
85
122
|
let className = "";
|
|
86
123
|
const percentageIndex = params.formattedValue.indexOf("(");
|
|
87
124
|
const costStr = percentageIndex === -1 ? params.formattedValue : params.formattedValue.substring(0, percentageIndex);
|
|
88
|
-
|
|
125
|
+
let percentageStr = percentageIndex === -1 ? "" : params.formattedValue.substring(percentageIndex);
|
|
89
126
|
if (percentageStr.includes("-")) {
|
|
90
127
|
className = classes.decrease;
|
|
128
|
+
percentageStr = percentageStr.replace("-", "\u25BC");
|
|
91
129
|
} else if (percentageStr.includes("+")) {
|
|
92
130
|
className = classes.increase;
|
|
131
|
+
percentageStr = percentageStr.replace("+", "\u25B2");
|
|
93
132
|
}
|
|
94
133
|
return /* @__PURE__ */ React.createElement(Typography, { variant: "body2" }, costStr, /* @__PURE__ */ React.createElement(Typography, { variant: "inherit", className }, percentageStr));
|
|
95
134
|
}
|
|
@@ -110,7 +149,11 @@ const CostReportsTableComponent = ({
|
|
|
110
149
|
},
|
|
111
150
|
valueFormatter: (value) => {
|
|
112
151
|
if (typeof value === "number") {
|
|
113
|
-
return `$${humanFormat(value, {
|
|
152
|
+
return `$${humanFormat(value, {
|
|
153
|
+
scale: customScale,
|
|
154
|
+
separator: "",
|
|
155
|
+
decimals: 2
|
|
156
|
+
})}`;
|
|
114
157
|
}
|
|
115
158
|
return "-";
|
|
116
159
|
},
|
|
@@ -134,8 +177,10 @@ const CostReportsTableComponent = ({
|
|
|
134
177
|
}
|
|
135
178
|
}
|
|
136
179
|
},
|
|
137
|
-
pageSizeOptions: [
|
|
138
|
-
|
|
180
|
+
pageSizeOptions: [15],
|
|
181
|
+
slots: { toolbar: CustomToolbar },
|
|
182
|
+
disableRowSelectionOnClick: true,
|
|
183
|
+
disableColumnMenu: true
|
|
139
184
|
}
|
|
140
185
|
));
|
|
141
186
|
};
|
|
@@ -1 +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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"}
|
|
1
|
+
{"version":3,"file":"CostReportsTableComponent.esm.js","sources":["../../../src/components/CostReportsTableComponent/CostReportsTableComponent.tsx"],"sourcesContent":["import Chip from '@material-ui/core/Chip';\nimport Typography from '@material-ui/core/Typography';\nimport { makeStyles } from '@material-ui/core/styles';\nimport Box from '@mui/material/Box';\nimport { DataGrid, GridColDef, GridRenderCellParams, GridToolbarContainer, GridToolbarExport } 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(theme => ({\n increase: {\n color: 'red',\n },\n decrease: {\n color: 'green',\n },\n container: {\n display: 'flex',\n alignItems: 'center',\n },\n clip: {\n backgroundColor: '#deebff',\n color: '#0052cc',\n marginLeft: theme.spacing(1),\n },\n}));\n\nfunction CustomToolbar() {\n return (\n <GridToolbarContainer>\n <GridToolbarExport printOptions={{ disableToolbarButton: true }} />\n </GridToolbarContainer>\n );\n}\n\nexport const CostReportsTableComponent: FC<CostReportsTableComponentProps> = ({\n reports,\n aggregatedBy,\n periods,\n}) => {\n const classes = useStyles();\n const customScale = humanFormat.Scale.create(['', 'K', 'M', 'B'], 1000);\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 let formattedValue = params.formattedValue;\n let chipLabel = null;\n\n if (aggregatedBy === 'service' || aggregatedBy === 'name') {\n if (\n params.formattedValue !== undefined &&\n params.formattedValue.indexOf('/') !== -1\n ) {\n const splitValue = params.formattedValue.split('/');\n formattedValue = splitValue[1];\n chipLabel = splitValue[0].toLowerCase();\n }\n }\n\n return (\n <Typography\n variant=\"body2\"\n component=\"div\"\n className={classes.container}\n >\n {formattedValue}\n {chipLabel && (\n <Chip size=\"small\" label={chipLabel} className={classes.clip} />\n )}\n </Typography>\n );\n },\n },\n {\n field: 'TREND',\n headerName: 'TREND',\n width: 100,\n disableExport: true,\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 = period.length === 7 ? getPreviousMonth(column.field) : '';\n const formattedValue = humanFormat(value, {\n scale: customScale,\n separator: '',\n decimals: 2,\n });\n if (\n periods.includes(previousPeriod) &&\n row.reports[previousPeriod] > 0\n ) {\n const diff =\n row.reports[column.field] - row.reports[previousPeriod];\n const percentage = Math.round(\n (diff / row.reports[previousPeriod]) * 100,\n );\n const mark = diff > 0 ? '+' : '';\n // only display percentage change if it is larger than 1% or less than -1%\n if (percentage >= 1 || percentage <= -1) {\n return `$${formattedValue} (${mark}${percentage}%)`;\n }\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 let percentageStr =\n percentageIndex === -1\n ? ''\n : params.formattedValue.substring(percentageIndex);\n if (percentageStr.includes('-')) {\n className = classes.decrease;\n percentageStr = percentageStr.replace('-', '▼');\n } else if (percentageStr.includes('+')) {\n className = classes.increase;\n percentageStr = percentageStr.replace('+', '▲');\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, {\n scale: customScale,\n separator: '',\n decimals: 2,\n })}`;\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={[15]}\n slots={{ toolbar: CustomToolbar }}\n disableRowSelectionOnClick\n disableColumnMenu\n />\n </Box>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { SvgIcon } from '@material-ui/core';
|
|
3
|
+
|
|
4
|
+
const InfraWalletIcon = () => {
|
|
5
|
+
return /* @__PURE__ */ React.createElement(SvgIcon, { x: "0px", y: "0px", viewBox: "0 0 24 24" }, /* @__PURE__ */ React.createElement("g", null, /* @__PURE__ */ React.createElement("g", null, /* @__PURE__ */ React.createElement("g", null, /* @__PURE__ */ React.createElement("g", null, /* @__PURE__ */ React.createElement("path", { fill: "#E8EAED;", d: "M10.37,4.55c0.02,0.01,0.04,0.03,0.06,0.04c0.37-0.52,0.86-0.88,1.42-1.04c0.3-0.08,0.61-0.1,0.93-0.07\n c-0.09-0.07-0.17-0.14-0.26-0.19c-0.41-0.28-0.83-0.42-1.22-0.42c-0.2,0-0.38,0.04-0.56,0.11C10.29,3.18,9.94,3.6,9.74,4.2\n C9.95,4.29,10.16,4.41,10.37,4.55z" }), /* @__PURE__ */ React.createElement("path", { fill: "#E8EAED;", d: "M20.47,7c-0.4-0.28-0.78-0.39-1.1-0.32l-0.5,0.11L18.72,6.3c-0.42-1.45-1.24-2.73-2.18-3.41\n c-0.57-0.41-1.15-0.57-1.63-0.44c-0.44,0.12-0.8,0.48-1.05,1.03l-0.13,0.29C13.97,3.87,14.2,4,14.42,4.17\n c1.04,0.75,1.93,2.06,2.45,3.57c0.48,0.02,0.98,0.2,1.46,0.54c1.61,1.12,2.8,3.85,2.78,6.33c0,0.15-0.01,0.29-0.02,0.43\n c0.27,0.06,0.51,0.03,0.73-0.09c0.57-0.34,0.93-1.31,0.95-2.53C22.79,10.3,21.78,7.92,20.47,7z" }))), /* @__PURE__ */ React.createElement("g", null, /* @__PURE__ */ React.createElement("path", { fill: "#E8EAED;", d: "M17.7,9.18c-0.4-0.28-0.78-0.39-1.1-0.32l-0.5,0.11l-0.14-0.49c-0.42-1.45-1.24-2.73-2.18-3.41\n c-0.57-0.41-1.15-0.57-1.63-0.44c-0.44,0.12-0.8,0.48-1.05,1.03l-0.13,0.29c0.23,0.11,0.46,0.24,0.69,0.41\n c1.04,0.75,1.93,2.06,2.45,3.57c0.48,0.02,0.98,0.2,1.46,0.54c1.61,1.12,2.8,3.85,2.78,6.33c0,0.15-0.01,0.29-0.02,0.43\n c0.27,0.06,0.51,0.03,0.73-0.09c0.57-0.34,0.93-1.31,0.95-2.53C20.02,12.47,19.01,10.1,17.7,9.18z" }), /* @__PURE__ */ React.createElement("path", { fill: "#E8EAED;", d: "M7.61,6.73c0.02,0.01,0.04,0.03,0.06,0.04c0.37-0.52,0.86-0.88,1.42-1.04c0.3-0.08,0.61-0.1,0.93-0.07\n C9.93,5.59,9.84,5.53,9.75,5.47C9.34,5.19,8.92,5.05,8.54,5.05c-0.2,0-0.38,0.04-0.56,0.11c-0.45,0.19-0.8,0.62-1.01,1.22\n C7.18,6.47,7.4,6.59,7.61,6.73z" })), /* @__PURE__ */ React.createElement("g", null, /* @__PURE__ */ React.createElement("path", { fill: "#E8EAED;", d: "M4.84,8.9C4.86,8.92,4.88,8.93,4.9,8.94c0.37-0.52,0.86-0.88,1.42-1.04c0.3-0.08,0.61-0.1,0.93-0.07\n C7.16,7.77,7.08,7.71,6.99,7.65C6.58,7.37,6.16,7.23,5.77,7.23c-0.2,0-0.38,0.04-0.56,0.11c-0.45,0.19-0.8,0.62-1.01,1.22\n C4.42,8.65,4.63,8.76,4.84,8.9z" }), /* @__PURE__ */ React.createElement("path", { fill: "#E8EAED;", d: "M14.94,11.36L14.94,11.36c-0.4-0.28-0.78-0.39-1.1-0.32l-0.5,0.11l-0.14-0.49\n c-0.42-1.45-1.24-2.73-2.18-3.41C10.44,6.83,9.86,6.67,9.38,6.8c-0.44,0.12-0.8,0.48-1.05,1.03L8.21,8.12\n C8.44,8.22,8.67,8.36,8.9,8.52c1.04,0.75,1.93,2.06,2.45,3.57c0.48,0.02,0.98,0.2,1.46,0.54c1.61,1.12,2.8,3.84,2.78,6.33\n c0,0.15-0.01,0.29-0.02,0.43c0.27,0.06,0.51,0.03,0.73-0.09c0.57-0.34,0.93-1.31,0.95-2.53C17.26,14.65,16.25,12.27,14.94,11.36z\n " })), /* @__PURE__ */ React.createElement("path", { fill: "#E8EAED;", d: "M11.92,19.4c-1.68-0.82-1.4-1.4-1.49-2.52v-0.16c0-0.95,0.67-1.37,1.49-0.93l2.32,1.24\n c-0.37-1.49-1.14-2.86-2.07-3.5l0,0c-0.4-0.28-0.78-0.39-1.1-0.32l-0.5,0.11l-0.14-0.49C10,11.37,9.19,10.1,8.25,9.42\n C7.67,9,7.09,8.85,6.61,8.98c-0.44,0.12-0.8,0.48-1.05,1.03l-0.31,0.71l-0.57-0.53c-0.15-0.14-0.3-0.26-0.46-0.36\n C3.81,9.55,3.39,9.4,3.01,9.4c-0.2,0-0.38,0.04-0.56,0.11c-0.57,0.24-0.98,0.86-1.14,1.74c-0.38,2.05,0.73,4.62,2.38,5.5\n l8.71,4.65c0.43,0.23,0.81,0.25,1.13,0.06c0.27-0.16,0.49-0.46,0.65-0.86L11.92,19.4z" }), /* @__PURE__ */ React.createElement("ellipse", { transform: "matrix(0.9086 -0.4176 0.4176 0.9086 -6.3391 6.8809)", fill: "#E8EAED;", cx: "12.55", cy: "17.93", rx: "0.63", ry: "0.98" }))));
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export { InfraWalletIcon };
|
|
9
|
+
//# sourceMappingURL=InfraWalletIcon.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InfraWalletIcon.esm.js","sources":["../../src/components/InfraWalletIcon.tsx"],"sourcesContent":["import React from 'react';\nimport { SvgIcon } from '@material-ui/core';\n\nexport const InfraWalletIcon = () => {\n return (\n <SvgIcon x=\"0px\" y=\"0px\" viewBox=\"0 0 24 24\">\n <g>\n <g>\n <g>\n <g>\n <path fill=\"#E8EAED;\" d=\"M10.37,4.55c0.02,0.01,0.04,0.03,0.06,0.04c0.37-0.52,0.86-0.88,1.42-1.04c0.3-0.08,0.61-0.1,0.93-0.07\n c-0.09-0.07-0.17-0.14-0.26-0.19c-0.41-0.28-0.83-0.42-1.22-0.42c-0.2,0-0.38,0.04-0.56,0.11C10.29,3.18,9.94,3.6,9.74,4.2\n C9.95,4.29,10.16,4.41,10.37,4.55z\"/>\n <path fill=\"#E8EAED;\" d=\"M20.47,7c-0.4-0.28-0.78-0.39-1.1-0.32l-0.5,0.11L18.72,6.3c-0.42-1.45-1.24-2.73-2.18-3.41\n c-0.57-0.41-1.15-0.57-1.63-0.44c-0.44,0.12-0.8,0.48-1.05,1.03l-0.13,0.29C13.97,3.87,14.2,4,14.42,4.17\n c1.04,0.75,1.93,2.06,2.45,3.57c0.48,0.02,0.98,0.2,1.46,0.54c1.61,1.12,2.8,3.85,2.78,6.33c0,0.15-0.01,0.29-0.02,0.43\n c0.27,0.06,0.51,0.03,0.73-0.09c0.57-0.34,0.93-1.31,0.95-2.53C22.79,10.3,21.78,7.92,20.47,7z\"/>\n </g>\n </g>\n <g>\n <path fill=\"#E8EAED;\" d=\"M17.7,9.18c-0.4-0.28-0.78-0.39-1.1-0.32l-0.5,0.11l-0.14-0.49c-0.42-1.45-1.24-2.73-2.18-3.41\n c-0.57-0.41-1.15-0.57-1.63-0.44c-0.44,0.12-0.8,0.48-1.05,1.03l-0.13,0.29c0.23,0.11,0.46,0.24,0.69,0.41\n c1.04,0.75,1.93,2.06,2.45,3.57c0.48,0.02,0.98,0.2,1.46,0.54c1.61,1.12,2.8,3.85,2.78,6.33c0,0.15-0.01,0.29-0.02,0.43\n c0.27,0.06,0.51,0.03,0.73-0.09c0.57-0.34,0.93-1.31,0.95-2.53C20.02,12.47,19.01,10.1,17.7,9.18z\"/>\n <path fill=\"#E8EAED;\" d=\"M7.61,6.73c0.02,0.01,0.04,0.03,0.06,0.04c0.37-0.52,0.86-0.88,1.42-1.04c0.3-0.08,0.61-0.1,0.93-0.07\n C9.93,5.59,9.84,5.53,9.75,5.47C9.34,5.19,8.92,5.05,8.54,5.05c-0.2,0-0.38,0.04-0.56,0.11c-0.45,0.19-0.8,0.62-1.01,1.22\n C7.18,6.47,7.4,6.59,7.61,6.73z\"/>\n </g>\n <g>\n <path fill=\"#E8EAED;\" d=\"M4.84,8.9C4.86,8.92,4.88,8.93,4.9,8.94c0.37-0.52,0.86-0.88,1.42-1.04c0.3-0.08,0.61-0.1,0.93-0.07\n C7.16,7.77,7.08,7.71,6.99,7.65C6.58,7.37,6.16,7.23,5.77,7.23c-0.2,0-0.38,0.04-0.56,0.11c-0.45,0.19-0.8,0.62-1.01,1.22\n C4.42,8.65,4.63,8.76,4.84,8.9z\"/>\n <path fill=\"#E8EAED;\" d=\"M14.94,11.36L14.94,11.36c-0.4-0.28-0.78-0.39-1.1-0.32l-0.5,0.11l-0.14-0.49\n c-0.42-1.45-1.24-2.73-2.18-3.41C10.44,6.83,9.86,6.67,9.38,6.8c-0.44,0.12-0.8,0.48-1.05,1.03L8.21,8.12\n C8.44,8.22,8.67,8.36,8.9,8.52c1.04,0.75,1.93,2.06,2.45,3.57c0.48,0.02,0.98,0.2,1.46,0.54c1.61,1.12,2.8,3.84,2.78,6.33\n c0,0.15-0.01,0.29-0.02,0.43c0.27,0.06,0.51,0.03,0.73-0.09c0.57-0.34,0.93-1.31,0.95-2.53C17.26,14.65,16.25,12.27,14.94,11.36z\n \"/>\n </g>\n <path fill=\"#E8EAED;\" d=\"M11.92,19.4c-1.68-0.82-1.4-1.4-1.49-2.52v-0.16c0-0.95,0.67-1.37,1.49-0.93l2.32,1.24\n c-0.37-1.49-1.14-2.86-2.07-3.5l0,0c-0.4-0.28-0.78-0.39-1.1-0.32l-0.5,0.11l-0.14-0.49C10,11.37,9.19,10.1,8.25,9.42\n C7.67,9,7.09,8.85,6.61,8.98c-0.44,0.12-0.8,0.48-1.05,1.03l-0.31,0.71l-0.57-0.53c-0.15-0.14-0.3-0.26-0.46-0.36\n C3.81,9.55,3.39,9.4,3.01,9.4c-0.2,0-0.38,0.04-0.56,0.11c-0.57,0.24-0.98,0.86-1.14,1.74c-0.38,2.05,0.73,4.62,2.38,5.5\n l8.71,4.65c0.43,0.23,0.81,0.25,1.13,0.06c0.27-0.16,0.49-0.46,0.65-0.86L11.92,19.4z\"/>\n\n <ellipse transform=\"matrix(0.9086 -0.4176 0.4176 0.9086 -6.3391 6.8809)\" fill=\"#E8EAED;\" cx=\"12.55\" cy=\"17.93\" rx=\"0.63\" ry=\"0.98\" />\n </g>\n </g>\n </SvgIcon>\n );\n}\n"],"names":[],"mappings":";;;AAGO,MAAM,kBAAkB,MAAM;AACnC,EAAA,2CACG,OAAQ,EAAA,EAAA,CAAA,EAAE,OAAM,CAAE,EAAA,KAAA,EAAM,SAAQ,WAC/B,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,2BACE,KAAA,CAAA,aAAA,CAAA,GAAA,EAAA,IAAA,sCACE,GACC,EAAA,IAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,2BACE,KAAA,CAAA,aAAA,CAAA,MAAA,EAAA,EAAK,MAAK,UAAW,EAAA,CAAA,EAAE,4SAEkB,EAAA,CAAA,sCACzC,MAAK,EAAA,EAAA,IAAA,EAAK,YAAW,CAAE,EAAA,qdAAA,EAG4E,CACtG,CACF,CAAA,sCACC,GACC,EAAA,IAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,UAAK,IAAK,EAAA,UAAA,EAAW,GAAE,gdAG6E,EAAA,CAAA,sCACpG,MAAK,EAAA,EAAA,IAAA,EAAK,UAAW,EAAA,CAAA,EAAE,iSAEa,CACvC,CAAA,sCACC,GACC,EAAA,IAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,UAAK,IAAK,EAAA,UAAA,EAAW,GAAE,6RAEa,EAAA,CAAA,sCACpC,MAAK,EAAA,EAAA,IAAA,EAAK,YAAW,CAAE,EAAA,kfAAA,EAIjB,CACT,CACA,kBAAA,KAAA,CAAA,aAAA,CAAC,UAAK,IAAK,EAAA,UAAA,EAAW,GAAE,yjBAI+D,EAAA,CAAA,sCAEtF,SAAQ,EAAA,EAAA,SAAA,EAAU,uDAAsD,IAAK,EAAA,UAAA,EAAW,IAAG,OAAQ,EAAA,EAAA,EAAG,SAAQ,EAAG,EAAA,MAAA,EAAO,IAAG,MAAO,EAAA,CACrI,CACF,CACF,CAAA,CAAA;AAEJ;;;;"}
|
|
@@ -31,7 +31,7 @@ const PieChartComponent = ({
|
|
|
31
31
|
labels: categories,
|
|
32
32
|
dataLabels: {
|
|
33
33
|
enabled: true,
|
|
34
|
-
formatter: (value, { seriesIndex,
|
|
34
|
+
formatter: (value, { seriesIndex, w }) => {
|
|
35
35
|
return `${w.config.labels[seriesIndex]} (${value.toFixed(0)}%)`;
|
|
36
36
|
}
|
|
37
37
|
},
|
|
@@ -1 +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,
|
|
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: number, { seriesIndex, w }: { seriesIndex: number, w: any }) => {\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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"}
|
|
@@ -4,7 +4,7 @@ import { Grid } from '@material-ui/core';
|
|
|
4
4
|
import { startOfMonth, addMonths, endOfMonth } from 'date-fns';
|
|
5
5
|
import React, { useState, useCallback, useEffect } from 'react';
|
|
6
6
|
import { infraWalletApiRef } from '../../api/InfraWalletApi.esm.js';
|
|
7
|
-
import { aggregateCostReports, mergeCostReports, getAllReportTags } from '../../api/functions.esm.js';
|
|
7
|
+
import { getPeriodStrings, aggregateCostReports, mergeCostReports, getAllReportTags } from '../../api/functions.esm.js';
|
|
8
8
|
import { ColumnsChartComponent } from '../ColumnsChartComponent/ColumnsChartComponent.esm.js';
|
|
9
9
|
import { CostReportsTableComponent } from '../CostReportsTableComponent/CostReportsTableComponent.esm.js';
|
|
10
10
|
import { PieChartComponent } from '../PieChartComponent/PieChartComponent.esm.js';
|
|
@@ -37,12 +37,13 @@ const ReportsComponent = () => {
|
|
|
37
37
|
const [reportTags, setReportTags] = useState([]);
|
|
38
38
|
const [granularity, setGranularity] = useState("monthly");
|
|
39
39
|
const [aggregatedBy, setAggregatedBy] = useState("none");
|
|
40
|
-
const [filters,
|
|
41
|
-
const [groups,
|
|
40
|
+
const [filters, _setFilters] = useState("");
|
|
41
|
+
const [groups, _setGroups] = useState("");
|
|
42
42
|
const [monthRangeState, setMonthRangeState] = React.useState({
|
|
43
43
|
startMonth: startOfMonth(addMonths(/* @__PURE__ */ new Date(), -2)),
|
|
44
44
|
endMonth: endOfMonth(/* @__PURE__ */ new Date())
|
|
45
45
|
});
|
|
46
|
+
const [periods, setPeriods] = useState([]);
|
|
46
47
|
const alertApi = useApi(alertApiRef);
|
|
47
48
|
const infraWalletApi = useApi(infraWalletApiRef);
|
|
48
49
|
const fetchCostReportsCallback = useCallback(async () => {
|
|
@@ -56,6 +57,13 @@ const ReportsComponent = () => {
|
|
|
56
57
|
).then((reportsResponse) => {
|
|
57
58
|
if (reportsResponse.data && reportsResponse.data.length > 0) {
|
|
58
59
|
setReports(reportsResponse.data);
|
|
60
|
+
setPeriods(
|
|
61
|
+
getPeriodStrings(
|
|
62
|
+
granularity,
|
|
63
|
+
monthRangeState.startMonth,
|
|
64
|
+
monthRangeState.endMonth
|
|
65
|
+
)
|
|
66
|
+
);
|
|
59
67
|
}
|
|
60
68
|
}).catch(
|
|
61
69
|
(e) => alertApi.post({ message: `${e.message}`, severity: "error" })
|
|
@@ -74,7 +82,7 @@ const ReportsComponent = () => {
|
|
|
74
82
|
setReportsAggregatedAndMerged(aggregatedAndMergedReports);
|
|
75
83
|
setReportTags(allTags);
|
|
76
84
|
}
|
|
77
|
-
}, [reports, aggregatedBy]);
|
|
85
|
+
}, [reports, aggregatedBy, granularity, monthRangeState]);
|
|
78
86
|
useEffect(() => {
|
|
79
87
|
fetchCostReportsCallback();
|
|
80
88
|
}, [fetchCostReportsCallback]);
|
|
@@ -84,8 +92,6 @@ const ReportsComponent = () => {
|
|
|
84
92
|
aggregatedBy,
|
|
85
93
|
aggregatedBySetter: setAggregatedBy,
|
|
86
94
|
tags: reportTags,
|
|
87
|
-
granularity,
|
|
88
|
-
granularitySetter: setGranularity,
|
|
89
95
|
monthRange: monthRangeState,
|
|
90
96
|
monthRangeSetter: setMonthRangeState
|
|
91
97
|
}
|
|
@@ -103,13 +109,11 @@ const ReportsComponent = () => {
|
|
|
103
109
|
)), /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 12, md: 8, lg: 9 }, reportsAggregatedAndMerged.length > 0 && /* @__PURE__ */ React.createElement(
|
|
104
110
|
ColumnsChartComponent,
|
|
105
111
|
{
|
|
106
|
-
|
|
112
|
+
granularitySetter: setGranularity,
|
|
113
|
+
categories: periods,
|
|
107
114
|
series: reportsAggregatedAndMerged.map((item) => ({
|
|
108
115
|
name: item.id,
|
|
109
|
-
data: rearrangeData(
|
|
110
|
-
item,
|
|
111
|
-
Object.keys(reportsAggregatedAndMerged[0].reports)
|
|
112
|
-
)
|
|
116
|
+
data: rearrangeData(item, periods)
|
|
113
117
|
})),
|
|
114
118
|
height: 350
|
|
115
119
|
}
|
|
@@ -117,7 +121,8 @@ const ReportsComponent = () => {
|
|
|
117
121
|
CostReportsTableComponent,
|
|
118
122
|
{
|
|
119
123
|
reports: reportsAggregated,
|
|
120
|
-
aggregatedBy
|
|
124
|
+
aggregatedBy,
|
|
125
|
+
periods
|
|
121
126
|
}
|
|
122
127
|
)))));
|
|
123
128
|
};
|
|
@@ -1 +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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"}
|
|
1
|
+
{"version":3,"file":"ReportsComponent.esm.js","sources":["../../../src/components/ReportsComponent/ReportsComponent.tsx"],"sourcesContent":["import { Content, Header, Page, Progress } 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 getPeriodStrings,\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 const [periods, setPeriods] = useState<string[]>([]);\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 setPeriods(\n getPeriodStrings(\n granularity,\n monthRangeState.startMonth,\n monthRangeState.endMonth,\n ),\n );\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, granularity, monthRangeState]);\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 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 granularitySetter={setGranularity}\n categories={periods}\n series={reportsAggregatedAndMerged.map((item: any) => ({\n name: item.id,\n data: rearrangeData(item, periods),\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 periods={periods}\n />\n )}\n </Grid>\n </Grid>\n </Content>\n </Page>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -20,8 +20,6 @@ const TopbarComponent = ({
|
|
|
20
20
|
aggregatedBy,
|
|
21
21
|
aggregatedBySetter,
|
|
22
22
|
tags,
|
|
23
|
-
granularity,
|
|
24
|
-
granularitySetter,
|
|
25
23
|
monthRange,
|
|
26
24
|
monthRangeSetter
|
|
27
25
|
}) => {
|
|
@@ -46,15 +44,7 @@ const TopbarComponent = ({
|
|
|
46
44
|
/* @__PURE__ */ React.createElement(Divider, { light: true }),
|
|
47
45
|
/* @__PURE__ */ React.createElement(ListSubheader, { onClickCapture: (e) => e.stopPropagation() }, "Tags"),
|
|
48
46
|
tags.map((tag) => /* @__PURE__ */ React.createElement(MenuItem, { key: tag, value: tag }, `tag:${tag}`))
|
|
49
|
-
)), /* @__PURE__ */ React.createElement(FormControl, { className: classes.formControl,
|
|
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(
|
|
47
|
+
)), /* @__PURE__ */ React.createElement(FormControl, { className: classes.formControl }, /* @__PURE__ */ React.createElement(LocalizationProvider, { dateAdapter: AdapterDateFns }, /* @__PURE__ */ React.createElement(
|
|
58
48
|
DatePicker,
|
|
59
49
|
{
|
|
60
50
|
value: monthRange.startMonth,
|
|
@@ -1 +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
|
|
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 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}>\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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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
2
|
import * as react from 'react';
|
|
3
|
+
import react__default from 'react';
|
|
3
4
|
import * as _backstage_core_plugin_api from '@backstage/core-plugin-api';
|
|
4
5
|
|
|
5
6
|
declare const infraWalletPlugin: _backstage_core_plugin_api.BackstagePlugin<{
|
|
@@ -7,4 +8,6 @@ declare const infraWalletPlugin: _backstage_core_plugin_api.BackstagePlugin<{
|
|
|
7
8
|
}, {}, {}>;
|
|
8
9
|
declare const InfraWalletPage: () => react.JSX.Element;
|
|
9
10
|
|
|
10
|
-
|
|
11
|
+
declare const InfraWalletIcon: () => react__default.JSX.Element;
|
|
12
|
+
|
|
13
|
+
export { InfraWalletIcon, InfraWalletPage, infraWalletPlugin };
|
package/dist/index.esm.js
CHANGED
package/dist/index.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|
|
1
|
+
{"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@electrolux-oss/plugin-infrawallet",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"backstage": {
|
|
5
5
|
"role": "frontend-plugin"
|
|
6
6
|
},
|
|
@@ -43,8 +43,7 @@
|
|
|
43
43
|
"@mui/x-data-grid": "7.3.1",
|
|
44
44
|
"@mui/x-date-pickers": "^6.20.0",
|
|
45
45
|
"@stitches/react": "1.2.8",
|
|
46
|
-
"@types/
|
|
47
|
-
"@types/react-date-range": "1.4.5",
|
|
46
|
+
"@types/react": "^18",
|
|
48
47
|
"@viniarruda/react-month-range-picker": "2.0.4",
|
|
49
48
|
"apexcharts": "3.42.0",
|
|
50
49
|
"better-react-mathjax": "^2.0.2",
|
|
@@ -67,6 +66,8 @@
|
|
|
67
66
|
"@testing-library/react": "^14.0.0",
|
|
68
67
|
"@testing-library/user-event": "^14.0.0",
|
|
69
68
|
"@types/lodash": "^4.14.151",
|
|
69
|
+
"@types/node-fetch": "^2.6.4",
|
|
70
|
+
"@types/react-date-range": "1.4.5",
|
|
70
71
|
"msw": "^1.0.0"
|
|
71
72
|
},
|
|
72
73
|
"peerDependencies": {
|