@electrolux-oss/plugin-infrawallet 1.1.0-20250929154750-e4ed5e3 → 1.1.0-20251202133007-1005ef9
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/dist/api/functions.esm.js +25 -2
- package/dist/api/functions.esm.js.map +1 -1
- package/dist/components/FiltersComponent/FiltersComponent.esm.js +11 -4
- package/dist/components/FiltersComponent/FiltersComponent.esm.js.map +1 -1
- package/dist/components/ReportsComponent/ReportsComponent.esm.js +44 -8
- package/dist/components/ReportsComponent/ReportsComponent.esm.js.map +1 -1
- package/dist/hooks/useInfraWalletLuceneParams.esm.js +192 -0
- package/dist/hooks/useInfraWalletLuceneParams.esm.js.map +1 -0
- package/package.json +3 -1
|
@@ -43,8 +43,31 @@ const filterCostReports = (reports, filters) => {
|
|
|
43
43
|
const filteredReports = reports.filter((report) => {
|
|
44
44
|
let match = true;
|
|
45
45
|
Object.keys(filters).forEach((key) => {
|
|
46
|
-
if (filters[key].length > 0
|
|
47
|
-
|
|
46
|
+
if (filters[key].length > 0) {
|
|
47
|
+
const reportValue = report[key];
|
|
48
|
+
if (reportValue === void 0) {
|
|
49
|
+
match = false;
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
const valueMatches = filters[key].some((filterValue) => {
|
|
53
|
+
if (reportValue === filterValue) {
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
if (key === "account") {
|
|
57
|
+
const baseAccountName = reportValue.split(" (")[0];
|
|
58
|
+
const filterAccountName = filterValue.split(" (")[0];
|
|
59
|
+
if (baseAccountName === filterAccountName) {
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
if (key === "service" && reportValue.includes("/") && filterValue.includes("/")) {
|
|
64
|
+
return reportValue === filterValue;
|
|
65
|
+
}
|
|
66
|
+
return false;
|
|
67
|
+
});
|
|
68
|
+
if (!valueMatches) {
|
|
69
|
+
match = false;
|
|
70
|
+
}
|
|
48
71
|
}
|
|
49
72
|
});
|
|
50
73
|
return match;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"functions.esm.js","sources":["../../src/api/functions.ts"],"sourcesContent":["import { format, parse, subDays, subMonths } from 'date-fns';\nimport { reduce } from 'lodash';\nimport moment from 'moment';\nimport { Filters, Report, Tag } from './types';\n\nexport const mergeCostReports = (reports: Report[], threshold?: number): 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 totalCosts.sort((a, b) => b.total - a.total);\n const idsToBeKept = totalCosts.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).sort((a, b) => a.id.localeCompare(b.id));\n};\n\nexport const filterCostReports = (reports: Report[], filters: Filters): Report[] => {\n const filteredReports = reports.filter(report => {\n let match = true;\n Object.keys(filters).forEach(key => {\n if (filters[key].length > 0 && !filters[key].includes(report[key] as string)) {\n match = false;\n }\n });\n return match;\n });\n\n return filteredReports;\n};\n\nexport const aggregateCostReports = (reports: Report[], aggregatedBy?: string): 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';\n }\n\n if (!accumulator[keyName]) {\n accumulator[keyName] = {\n id: keyName,\n provider: report.provider,\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 getReportKeyAndValues = (reports: Report[] | undefined): { [key: string]: string[] } => {\n const excludedKeys = ['id', 'reports'];\n const keyValueSets: { [key: string]: Set<string> } = {};\n reports?.forEach(report => {\n Object.keys(report).forEach(key => {\n if (!excludedKeys.includes(key)) {\n if (keyValueSets[key] === undefined) {\n keyValueSets[key] = new Set<string>();\n }\n\n keyValueSets[key].add(report[key] as string);\n }\n });\n });\n\n const keyValues: { [key: string]: string[] } = {};\n Object.keys(keyValueSets).forEach((key: string) => {\n keyValues[key] = Array.from(keyValueSets[key]);\n keyValues[key].sort((a, b) => a.localeCompare(b));\n });\n return keyValues;\n};\n\nexport const extractProvider = (input: string): string | undefined => {\n let provider = undefined;\n if (input && input.indexOf('/') !== -1) {\n provider = input.split('/')[0];\n }\n\n return provider;\n};\n\nexport const extractAccountInfo = (input: string): { accountName: string; accountId?: string } => {\n // try to match format: accountName (accountId), e.g. aws-dev (123456789012)\n const regex = /^(.*?)\\s*\\(([^)]+)\\)$/;\n const match = input.match(regex);\n\n if (match) {\n const accountName = match[1];\n const accountId = match[2];\n return { accountName: accountName, accountId: accountId };\n }\n\n return { accountName: input };\n};\n\n// check if targetTag exists in tags\nexport function tagExists(tags: Tag[], targetTag: Tag): boolean {\n return tags.some(\n tag => tag.provider === targetTag.provider && tag.key === targetTag.key && tag.value === targetTag.value,\n );\n}\n\n// convert Tag array to (provider1:key1=value1 OR provider2:key2=value2) format\nexport const tagsToString = (tags: Tag[]): string => {\n if (tags.length === 0) {\n return '()';\n }\n\n const keyValuePairs = tags.map(tag => `${tag.provider}:${tag.key}=${tag.value}`);\n return `(${keyValuePairs.join(' OR ')})`;\n};\n\nexport const getAllReportTags = (reports: Report[]): string[] => {\n const tags = new Set<string>();\n const reservedKeys = ['id', 'account', 'service', 'category', 'provider', 'reports'];\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 getPreviousDay = (day: string): string => {\n const date = parse(day, 'yyyy-MM-dd', new Date());\n const previousDay = subDays(date, 1);\n return format(previousDay, 'yyyy-MM-dd');\n};\n\nexport const getPeriodStrings = (granularity: string, startTime: Date, endTime: Date): 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\nexport const formatCurrency = (number: number, currency?: string): string => {\n return new Intl.NumberFormat('en-US', {\n style: 'currency',\n currency: currency || 'USD',\n notation: 'compact',\n }).format(number);\n};\n\nexport interface BudgetAnalytics {\n yearToDateSpent: number;\n monthlyRunRate: number;\n projectedAnnualSpending: number;\n budgetHealthStatus: 'healthy' | 'warning' | 'critical';\n budgetUtilizationPercent: number;\n targetMonthlySpending: number;\n monthsRemaining: number;\n averageMonthlySpending: number;\n spendingVelocity: number;\n confidenceRange: {\n low: number;\n high: number;\n };\n}\n\nexport const calculateBudgetAnalytics = (\n monthlyCosts: Record<string, number>,\n annualBudget: number,\n): BudgetAnalytics => {\n const currentMonth = moment().month() + 1;\n const currentYear = moment().year();\n const daysIntoCurrentMonth = moment().date();\n const daysInCurrentMonth = moment().daysInMonth();\n\n let yearToDateSpent = 0;\n const monthlySpending: number[] = [];\n\n for (let month = 1; month <= currentMonth; month++) {\n const monthKey = `${currentYear}-${month.toString().padStart(2, '0')}`;\n const monthCost = monthlyCosts[monthKey] || 0;\n\n if (month < currentMonth) {\n yearToDateSpent += monthCost;\n monthlySpending.push(monthCost);\n } else if (month === currentMonth) {\n const projectedCurrentMonthCost = (monthCost / daysIntoCurrentMonth) * daysInCurrentMonth;\n yearToDateSpent += monthCost;\n monthlySpending.push(projectedCurrentMonthCost);\n }\n }\n\n const monthsRemaining = 12 - currentMonth + (1 - daysIntoCurrentMonth / daysInCurrentMonth);\n const averageMonthlySpending =\n monthlySpending.length > 0 ? monthlySpending.reduce((sum, cost) => sum + cost, 0) / monthlySpending.length : 0;\n\n const monthlyRunRate = monthlySpending.length > 0 ? monthlySpending[monthlySpending.length - 1] || 0 : 0;\n\n const projectedAnnualSpending = yearToDateSpent + averageMonthlySpending * monthsRemaining;\n\n const budgetUtilizationPercent = annualBudget > 0 ? (yearToDateSpent / annualBudget) * 100 : 0;\n const expectedUtilizationPercent = ((currentMonth - 1 + daysIntoCurrentMonth / daysInCurrentMonth) / 12) * 100;\n\n let budgetHealthStatus: 'healthy' | 'warning' | 'critical' = 'healthy';\n if (budgetUtilizationPercent > expectedUtilizationPercent + 20) {\n budgetHealthStatus = 'critical';\n } else if (budgetUtilizationPercent > expectedUtilizationPercent + 10) {\n budgetHealthStatus = 'warning';\n }\n\n const targetMonthlySpending = monthsRemaining > 0 ? (annualBudget - yearToDateSpent) / monthsRemaining : 0;\n\n const spendingVariance =\n monthlySpending.length > 1\n ? Math.sqrt(\n monthlySpending.reduce((sum, cost) => sum + Math.pow(cost - averageMonthlySpending, 2), 0) /\n (monthlySpending.length - 1),\n )\n : 0;\n\n const spendingVelocity =\n monthlySpending.length >= 2\n ? ((monthlySpending[monthlySpending.length - 1] - monthlySpending[monthlySpending.length - 2]) /\n monthlySpending[monthlySpending.length - 2]) *\n 100\n : 0;\n\n const confidenceRange = {\n low: Math.max(0, projectedAnnualSpending - spendingVariance * 2 * Math.sqrt(monthsRemaining)),\n high: projectedAnnualSpending + spendingVariance * 2 * Math.sqrt(monthsRemaining),\n };\n\n return {\n yearToDateSpent,\n monthlyRunRate,\n projectedAnnualSpending,\n budgetHealthStatus,\n budgetUtilizationPercent,\n targetMonthlySpending,\n monthsRemaining,\n averageMonthlySpending,\n spendingVelocity,\n confidenceRange,\n };\n};\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"functions.esm.js","sources":["../../src/api/functions.ts"],"sourcesContent":["import { format, parse, subDays, subMonths } from 'date-fns';\nimport { reduce } from 'lodash';\nimport moment from 'moment';\nimport { Filters, Report, Tag } from './types';\n\nexport const mergeCostReports = (reports: Report[], threshold?: number): 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 totalCosts.sort((a, b) => b.total - a.total);\n const idsToBeKept = totalCosts.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).sort((a, b) => a.id.localeCompare(b.id));\n};\n\nexport const filterCostReports = (reports: Report[], filters: Filters): Report[] => {\n const filteredReports = reports.filter(report => {\n let match = true;\n Object.keys(filters).forEach(key => {\n if (filters[key].length > 0) {\n const reportValue = report[key] as string | undefined;\n\n // If the report doesn't have this field at all, it doesn't match\n if (reportValue === undefined) {\n match = false;\n return;\n }\n\n // Check if the report value matches any of the filter values\n const valueMatches = filters[key].some(filterValue => {\n // For exact matches\n if (reportValue === filterValue) {\n return true;\n }\n\n // For account field: match with or without account ID suffix\n // e.g., \"AWS/aws-staging-mock\" should match \"AWS/aws-staging-mock (012345678901)\"\n if (key === 'account') {\n // Extract the base account name (everything before the parentheses)\n const baseAccountName = reportValue.split(' (')[0];\n const filterAccountName = filterValue.split(' (')[0];\n if (baseAccountName === filterAccountName) {\n return true;\n }\n }\n\n // For service field: handle provider prefix matching\n // e.g., \"AWS/Lambda\" in filter should match \"AWS/Lambda\" in report\n if (key === 'service' && reportValue.includes('/') && filterValue.includes('/')) {\n return reportValue === filterValue;\n }\n\n return false;\n });\n\n if (!valueMatches) {\n match = false;\n }\n }\n });\n return match;\n });\n\n return filteredReports;\n};\n\nexport const aggregateCostReports = (reports: Report[], aggregatedBy?: string): 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';\n }\n\n if (!accumulator[keyName]) {\n accumulator[keyName] = {\n id: keyName,\n provider: report.provider,\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 getReportKeyAndValues = (reports: Report[] | undefined): { [key: string]: string[] } => {\n const excludedKeys = ['id', 'reports'];\n const keyValueSets: { [key: string]: Set<string> } = {};\n reports?.forEach(report => {\n Object.keys(report).forEach(key => {\n if (!excludedKeys.includes(key)) {\n if (keyValueSets[key] === undefined) {\n keyValueSets[key] = new Set<string>();\n }\n\n keyValueSets[key].add(report[key] as string);\n }\n });\n });\n\n const keyValues: { [key: string]: string[] } = {};\n Object.keys(keyValueSets).forEach((key: string) => {\n keyValues[key] = Array.from(keyValueSets[key]);\n keyValues[key].sort((a, b) => a.localeCompare(b));\n });\n return keyValues;\n};\n\nexport const extractProvider = (input: string): string | undefined => {\n let provider = undefined;\n if (input && input.indexOf('/') !== -1) {\n provider = input.split('/')[0];\n }\n\n return provider;\n};\n\nexport const extractAccountInfo = (input: string): { accountName: string; accountId?: string } => {\n // try to match format: accountName (accountId), e.g. aws-dev (123456789012)\n const regex = /^(.*?)\\s*\\(([^)]+)\\)$/;\n const match = input.match(regex);\n\n if (match) {\n const accountName = match[1];\n const accountId = match[2];\n return { accountName: accountName, accountId: accountId };\n }\n\n return { accountName: input };\n};\n\n// check if targetTag exists in tags\nexport function tagExists(tags: Tag[], targetTag: Tag): boolean {\n return tags.some(\n tag => tag.provider === targetTag.provider && tag.key === targetTag.key && tag.value === targetTag.value,\n );\n}\n\n// convert Tag array to (provider1:key1=value1 OR provider2:key2=value2) format\nexport const tagsToString = (tags: Tag[]): string => {\n if (tags.length === 0) {\n return '()';\n }\n\n const keyValuePairs = tags.map(tag => `${tag.provider}:${tag.key}=${tag.value}`);\n return `(${keyValuePairs.join(' OR ')})`;\n};\n\nexport const getAllReportTags = (reports: Report[]): string[] => {\n const tags = new Set<string>();\n const reservedKeys = ['id', 'account', 'service', 'category', 'provider', 'reports'];\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 getPreviousDay = (day: string): string => {\n const date = parse(day, 'yyyy-MM-dd', new Date());\n const previousDay = subDays(date, 1);\n return format(previousDay, 'yyyy-MM-dd');\n};\n\nexport const getPeriodStrings = (granularity: string, startTime: Date, endTime: Date): 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\nexport const formatCurrency = (number: number, currency?: string): string => {\n return new Intl.NumberFormat('en-US', {\n style: 'currency',\n currency: currency || 'USD',\n notation: 'compact',\n }).format(number);\n};\n\nexport interface BudgetAnalytics {\n yearToDateSpent: number;\n monthlyRunRate: number;\n projectedAnnualSpending: number;\n budgetHealthStatus: 'healthy' | 'warning' | 'critical';\n budgetUtilizationPercent: number;\n targetMonthlySpending: number;\n monthsRemaining: number;\n averageMonthlySpending: number;\n spendingVelocity: number;\n confidenceRange: {\n low: number;\n high: number;\n };\n}\n\nexport const calculateBudgetAnalytics = (\n monthlyCosts: Record<string, number>,\n annualBudget: number,\n): BudgetAnalytics => {\n const currentMonth = moment().month() + 1;\n const currentYear = moment().year();\n const daysIntoCurrentMonth = moment().date();\n const daysInCurrentMonth = moment().daysInMonth();\n\n let yearToDateSpent = 0;\n const monthlySpending: number[] = [];\n\n for (let month = 1; month <= currentMonth; month++) {\n const monthKey = `${currentYear}-${month.toString().padStart(2, '0')}`;\n const monthCost = monthlyCosts[monthKey] || 0;\n\n if (month < currentMonth) {\n yearToDateSpent += monthCost;\n monthlySpending.push(monthCost);\n } else if (month === currentMonth) {\n const projectedCurrentMonthCost = (monthCost / daysIntoCurrentMonth) * daysInCurrentMonth;\n yearToDateSpent += monthCost;\n monthlySpending.push(projectedCurrentMonthCost);\n }\n }\n\n const monthsRemaining = 12 - currentMonth + (1 - daysIntoCurrentMonth / daysInCurrentMonth);\n const averageMonthlySpending =\n monthlySpending.length > 0 ? monthlySpending.reduce((sum, cost) => sum + cost, 0) / monthlySpending.length : 0;\n\n const monthlyRunRate = monthlySpending.length > 0 ? monthlySpending[monthlySpending.length - 1] || 0 : 0;\n\n const projectedAnnualSpending = yearToDateSpent + averageMonthlySpending * monthsRemaining;\n\n const budgetUtilizationPercent = annualBudget > 0 ? (yearToDateSpent / annualBudget) * 100 : 0;\n const expectedUtilizationPercent = ((currentMonth - 1 + daysIntoCurrentMonth / daysInCurrentMonth) / 12) * 100;\n\n let budgetHealthStatus: 'healthy' | 'warning' | 'critical' = 'healthy';\n if (budgetUtilizationPercent > expectedUtilizationPercent + 20) {\n budgetHealthStatus = 'critical';\n } else if (budgetUtilizationPercent > expectedUtilizationPercent + 10) {\n budgetHealthStatus = 'warning';\n }\n\n const targetMonthlySpending = monthsRemaining > 0 ? (annualBudget - yearToDateSpent) / monthsRemaining : 0;\n\n const spendingVariance =\n monthlySpending.length > 1\n ? Math.sqrt(\n monthlySpending.reduce((sum, cost) => sum + Math.pow(cost - averageMonthlySpending, 2), 0) /\n (monthlySpending.length - 1),\n )\n : 0;\n\n const spendingVelocity =\n monthlySpending.length >= 2\n ? ((monthlySpending[monthlySpending.length - 1] - monthlySpending[monthlySpending.length - 2]) /\n monthlySpending[monthlySpending.length - 2]) *\n 100\n : 0;\n\n const confidenceRange = {\n low: Math.max(0, projectedAnnualSpending - spendingVariance * 2 * Math.sqrt(monthsRemaining)),\n high: projectedAnnualSpending + spendingVariance * 2 * Math.sqrt(monthsRemaining),\n };\n\n return {\n yearToDateSpent,\n monthlyRunRate,\n projectedAnnualSpending,\n budgetHealthStatus,\n budgetUtilizationPercent,\n targetMonthlySpending,\n monthsRemaining,\n averageMonthlySpending,\n spendingVelocity,\n confidenceRange,\n };\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -35,6 +35,7 @@ const FiltersComponent = ({
|
|
|
35
35
|
filters,
|
|
36
36
|
monthRange,
|
|
37
37
|
filtersSetter,
|
|
38
|
+
selectedTags: selectedTagsProp,
|
|
38
39
|
selectedTagsSetter,
|
|
39
40
|
providerErrorsSetter
|
|
40
41
|
}) => {
|
|
@@ -51,11 +52,12 @@ const FiltersComponent = ({
|
|
|
51
52
|
const [tagValues, setTagValues] = useState(void 0);
|
|
52
53
|
const [resetTagValues, setResetTagValues] = useState(false);
|
|
53
54
|
const loadingTagValues = openTagValue && tagValues === void 0;
|
|
54
|
-
const [selectedTags, setSelectedTags] = useState([]);
|
|
55
|
+
const [selectedTags, setSelectedTags] = useState(selectedTagsProp || []);
|
|
55
56
|
const infraWalletApi = useApi(infraWalletApiRef);
|
|
56
57
|
const alertApi = useApi(alertApiRef);
|
|
57
58
|
const handleFiltersChange = (key, newValue) => {
|
|
58
|
-
|
|
59
|
+
const updatedFilters = { ...filters, [key]: newValue };
|
|
60
|
+
filtersSetter(updatedFilters);
|
|
59
61
|
};
|
|
60
62
|
const handleTagProviderChange = (provider) => {
|
|
61
63
|
setTagProvider("");
|
|
@@ -68,6 +70,10 @@ const FiltersComponent = ({
|
|
|
68
70
|
if (provider) {
|
|
69
71
|
setTagProvider(provider);
|
|
70
72
|
setOpenTagKey(true);
|
|
73
|
+
const currentProviderFilters = filters.provider || [];
|
|
74
|
+
if (!currentProviderFilters.includes(provider)) {
|
|
75
|
+
handleFiltersChange("provider", [...currentProviderFilters, provider]);
|
|
76
|
+
}
|
|
71
77
|
}
|
|
72
78
|
};
|
|
73
79
|
const handleTagKeyChange = (tagKey) => {
|
|
@@ -143,9 +149,10 @@ const FiltersComponent = ({
|
|
|
143
149
|
{
|
|
144
150
|
multiple: true,
|
|
145
151
|
id: `checkboxes-${key}`,
|
|
146
|
-
options: keyValues[key],
|
|
147
|
-
value: filters[key] || [],
|
|
152
|
+
options: keyValues[key] || [],
|
|
153
|
+
value: (filters[key] || []).filter((v) => (keyValues[key] || []).includes(v)),
|
|
148
154
|
onChange: (_event, value, _reason) => handleFiltersChange(key, value),
|
|
155
|
+
isOptionEqualToValue: (option, value) => option === value,
|
|
149
156
|
disableCloseOnSelect: true,
|
|
150
157
|
renderOption: (props, option, { selected }) => {
|
|
151
158
|
let provider = void 0;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FiltersComponent.esm.js","sources":["../../../src/components/FiltersComponent/FiltersComponent.tsx"],"sourcesContent":["import { alertApiRef, useApi } from '@backstage/core-plugin-api';\nimport CheckBoxIcon from '@mui/icons-material/CheckBox';\nimport CheckBoxOutlineBlankIcon from '@mui/icons-material/CheckBoxOutlineBlank';\nimport Autocomplete from '@mui/material/Autocomplete';\nimport Button from '@mui/material/Button';\nimport Checkbox from '@mui/material/Checkbox';\nimport Chip from '@mui/material/Chip';\nimport CircularProgress from '@mui/material/CircularProgress';\nimport Divider from '@mui/material/Divider';\nimport FormControl from '@mui/material/FormControl';\nimport Grid from '@mui/material/Grid';\nimport TextField from '@mui/material/TextField';\nimport Tooltip from '@mui/material/Tooltip';\nimport Typography from '@mui/material/Typography';\nimport { Theme, useTheme } from '@mui/material/styles';\nimport { withStyles } from '@mui/styles';\nimport { FC, default as React, useEffect, useState } from 'react';\nimport { infraWalletApiRef } from '../../api/InfraWalletApi';\nimport { extractAccountInfo, extractProvider, getReportKeyAndValues, tagExists } from '../../api/functions';\nimport { Tag } from '../../api/types';\nimport { ProviderIcon } from '../ProviderIcon';\nimport { FiltersComponentProps } from '../types';\n\nconst icon = <CheckBoxOutlineBlankIcon fontSize=\"small\" />;\nconst checkedIcon = <CheckBoxIcon fontSize=\"small\" />;\n\nconst HtmlTooltip = withStyles((theme: Theme) => ({\n tooltip: {\n backgroundColor: '#f5f5f9',\n color: 'rgba(0, 0, 0, 0.87)',\n maxWidth: 400,\n fontSize: typeof theme.typography?.pxToRem === 'function' ? theme.typography.pxToRem(14) : '14px',\n border: '1px solid #dadde9',\n },\n}))(Tooltip);\n\nexport const FiltersComponent: FC<FiltersComponentProps> = ({\n reports,\n filters,\n monthRange,\n filtersSetter,\n selectedTagsSetter,\n providerErrorsSetter,\n}) => {\n const theme = useTheme();\n const keyValues: { [key: string]: string[] } = getReportKeyAndValues(reports);\n\n // tag providers\n const [tagProviders, _setTagProviders] = useState<string[]>(['AWS', 'Azure']);\n const [tagProvider, setTagProvider] = useState<string>();\n\n // tag keys\n const [openTagKey, setOpenTagKey] = useState(false);\n const [tagKeys, setTagKeys] = useState<Tag[] | undefined>(undefined);\n const [selectedTagKey, setSelectedTagKey] = useState<Tag | undefined>(undefined);\n const [resetTagKeys, setResetTagKeys] = useState(false);\n const loadingTagKeys = openTagKey && tagKeys === undefined;\n\n // tag values\n const [openTagValue, setOpenTagValue] = useState(false);\n const [tagValues, setTagValues] = useState<Tag[] | undefined>(undefined);\n const [resetTagValues, setResetTagValues] = useState(false);\n const loadingTagValues = openTagValue && tagValues === undefined;\n\n // user selected tags\n const [selectedTags, setSelectedTags] = useState<Tag[]>([]);\n\n const infraWalletApi = useApi(infraWalletApiRef);\n const alertApi = useApi(alertApiRef);\n\n const handleFiltersChange = (key: string, newValue: string[]): void => {\n filtersSetter({ ...filters, [key]: newValue });\n };\n\n const handleTagProviderChange = (provider: string | null) => {\n setTagProvider('');\n setOpenTagKey(false);\n setResetTagKeys(prev => !prev);\n setTagKeys(undefined);\n setSelectedTagKey(undefined);\n setOpenTagValue(false);\n setTagValues([]);\n\n if (provider) {\n setTagProvider(provider);\n setOpenTagKey(true);\n }\n };\n\n const handleTagKeyChange = (tagKey: Tag | string | null) => {\n setSelectedTagKey(undefined);\n setTagValues(undefined);\n setResetTagValues(prev => !prev);\n\n if (typeof tagKey === 'string') {\n return;\n }\n\n if (tagKey) {\n setSelectedTagKey(tagKey);\n setOpenTagValue(true);\n }\n };\n\n const handleTagValueSelection = (tag: Tag | string | null) => {\n if (typeof tag === 'string') {\n return;\n }\n\n if (tag && !tagExists(selectedTags, tag)) {\n setResetTagValues(prev => !prev);\n setSelectedTags([...selectedTags, tag]);\n }\n };\n\n const handleDeleteTag = (tagToDelete: Tag) => () => {\n setSelectedTags(\n selectedTags.filter(\n tag =>\n !(tag.provider === tagToDelete.provider && tag.key === tagToDelete.key && tag.value === tagToDelete.value),\n ),\n );\n };\n\n useEffect(() => {\n if (!loadingTagKeys) {\n return;\n }\n\n (async () => {\n if (tagProvider) {\n await infraWalletApi\n .getTagKeys(tagProvider, monthRange.startMonth, monthRange.endMonth)\n .then(response => {\n if (response.data) {\n setTagKeys(response.data);\n }\n if (response.status === 207 && response.errors) {\n providerErrorsSetter(response.errors);\n }\n })\n .catch(e => alertApi.post({ message: `${e.message}`, severity: 'error' }));\n }\n })();\n }, [loadingTagKeys, tagProvider, monthRange, infraWalletApi, alertApi, providerErrorsSetter]);\n\n useEffect(() => {\n if (!loadingTagValues) {\n return;\n }\n\n (async () => {\n if (selectedTagKey) {\n await infraWalletApi\n .getTagValues(selectedTagKey, monthRange.startMonth, monthRange.endMonth)\n .then(response => {\n if (response.data) {\n setTagValues(response.data);\n }\n if (response.status === 207 && response.errors) {\n providerErrorsSetter(response.errors);\n }\n })\n .catch(e => alertApi.post({ message: `${e.message}`, severity: 'error' }));\n }\n })();\n }, [loadingTagValues, selectedTagKey, monthRange, infraWalletApi, alertApi, providerErrorsSetter]);\n\n return (\n <Grid container>\n <Grid item xs={12}>\n {Object.keys(keyValues).map(key => (\n <FormControl\n key={`form-${key}`}\n sx={{ marginLeft: theme.spacing(1), marginRight: theme.spacing(3), minWidth: 300 }}\n >\n <Autocomplete\n multiple\n id={`checkboxes-${key}`}\n options={keyValues[key]}\n value={filters[key] || []}\n onChange={(_event, value: string[], _reason) => handleFiltersChange(key, value)}\n disableCloseOnSelect\n renderOption={(props, option, { selected }) => {\n let provider = undefined;\n let providerIcon = undefined;\n let accountName = undefined;\n let accountId = undefined;\n if (key === 'provider') {\n provider = option;\n providerIcon = <ProviderIcon provider={provider} />;\n } else if (['account', 'service'].includes(key)) {\n provider = extractProvider(option);\n providerIcon = <ProviderIcon provider={provider} />;\n }\n\n if (key === 'account') {\n const account = extractAccountInfo(option.replace(`${provider}/`, ''));\n accountName = account.accountName;\n accountId = account.accountId;\n }\n\n return (\n <li {...props} key={option}>\n <Checkbox icon={icon} checkedIcon={checkedIcon} style={{ marginRight: 8 }} checked={selected} />\n {providerIcon && <>{providerIcon} </>}\n {key === 'account' ? (\n <div>\n <Typography variant=\"body2\">{accountName}</Typography>\n <Typography variant=\"caption\" color=\"textSecondary\">\n {accountId}\n </Typography>\n </div>\n ) : (\n <Typography variant=\"body2\">{option.replace(`${provider}/`, '')}</Typography>\n )}\n </li>\n );\n }}\n renderInput={params => (\n <TextField {...params} variant=\"standard\" label={key.charAt(0).toUpperCase() + key.slice(1)} />\n )}\n />\n </FormControl>\n ))}\n <FormControl style={{ marginTop: 10 }}>\n <Button variant=\"contained\" color=\"primary\" onClick={() => filtersSetter({})}>\n Clear filters\n </Button>\n </FormControl>\n </Grid>\n <Grid item xs={12}>\n <Divider />\n </Grid>\n <Grid item xs={12}>\n <FormControl sx={{ marginLeft: theme.spacing(1), marginRight: theme.spacing(3), minWidth: 300 }}>\n <Autocomplete\n id=\"tag-providers\"\n options={tagProviders}\n onChange={(_, provider) => handleTagProviderChange(provider)}\n renderInput={params => <TextField {...params} variant=\"standard\" label=\"Tag provider\" />}\n renderOption={(props, option) => (\n <li {...props} key={option}>\n <Typography variant=\"body2\">{option}</Typography>\n </li>\n )}\n />\n </FormControl>\n <FormControl sx={{ marginLeft: theme.spacing(1), marginRight: theme.spacing(3), minWidth: 300 }}>\n <Autocomplete\n id=\"tag-keys\"\n key={String(resetTagKeys)}\n // freeSolo\n disabled={!tagProvider}\n open={openTagKey}\n onOpen={() => setOpenTagKey(true)}\n onClose={() => setOpenTagKey(false)}\n options={tagKeys?.length ? tagKeys : [{ key: 'No value', provider: tagProvider as string }]}\n getOptionLabel={tag => tag.key}\n getOptionDisabled={tag => tag.key === 'No value'}\n loading={loadingTagKeys}\n onChange={(_, tagKey) => handleTagKeyChange(tagKey)}\n renderInput={params => (\n <TextField\n {...params}\n variant=\"standard\"\n label=\"Tag keys\"\n InputProps={{\n ...params.InputProps,\n endAdornment: (\n <React.Fragment>\n {loadingTagKeys ? <CircularProgress color=\"inherit\" size={20} /> : null}\n {params.InputProps?.endAdornment}\n </React.Fragment>\n ),\n }}\n />\n )}\n renderOption={(props, option) => (\n <li {...props} key={option.key}>\n <Typography variant=\"body2\">{option.key}</Typography>\n </li>\n )}\n />\n </FormControl>\n <FormControl sx={{ marginLeft: theme.spacing(1), marginRight: theme.spacing(3), minWidth: 300 }}>\n <Autocomplete\n id=\"tag-values\"\n key={String(resetTagValues)}\n // freeSolo\n disabled={!selectedTagKey}\n open={openTagValue}\n onOpen={() => setOpenTagValue(true)}\n onClose={() => setOpenTagValue(false)}\n options={\n tagValues?.length ? tagValues : [{ key: 'No value', value: 'No value', provider: tagProvider as string }]\n }\n getOptionLabel={tag => tag?.value || ''}\n getOptionDisabled={tag => tag?.value === 'No value' || tagExists(selectedTags, tag)}\n loading={loadingTagValues}\n onChange={(_, tag) => handleTagValueSelection(tag)}\n renderInput={params => (\n <TextField\n {...params}\n variant=\"standard\"\n label=\"Tag values\"\n InputProps={{\n ...params.InputProps,\n endAdornment: (\n <React.Fragment>\n {loadingTagValues ? <CircularProgress color=\"inherit\" size={20} /> : null}\n {params.InputProps?.endAdornment}\n </React.Fragment>\n ),\n }}\n />\n )}\n renderOption={(props, option) => (\n <li {...props} key={option.value}>\n <Typography variant=\"body2\">{option.value}</Typography>\n </li>\n )}\n />\n </FormControl>\n <FormControl style={{ marginTop: 10 }}>\n <HtmlTooltip\n title={\n <React.Fragment>\n You can apply <b>tags</b> to <em>one or more</em> providers. <b>Tags</b> will only filter the costs for\n the <b>selected providers</b>, while <em>others remain unchanged</em>.\n </React.Fragment>\n }\n >\n <Button variant=\"contained\" color=\"primary\" onClick={() => selectedTagsSetter(selectedTags)}>\n Apply\n </Button>\n </HtmlTooltip>\n </FormControl>\n </Grid>\n <Grid item xs={12}>\n {selectedTags.map(tag => (\n <Chip\n size=\"small\"\n key={`${tag.provider}/${tag.key}=${tag.value}`}\n label={`${tag.provider}/${tag.key}=${tag.value}`}\n onDelete={handleDeleteTag(tag)}\n />\n ))}\n </Grid>\n </Grid>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"FiltersComponent.esm.js","sources":["../../../src/components/FiltersComponent/FiltersComponent.tsx"],"sourcesContent":["import { alertApiRef, useApi } from '@backstage/core-plugin-api';\nimport CheckBoxIcon from '@mui/icons-material/CheckBox';\nimport CheckBoxOutlineBlankIcon from '@mui/icons-material/CheckBoxOutlineBlank';\nimport Autocomplete from '@mui/material/Autocomplete';\nimport Button from '@mui/material/Button';\nimport Checkbox from '@mui/material/Checkbox';\nimport Chip from '@mui/material/Chip';\nimport CircularProgress from '@mui/material/CircularProgress';\nimport Divider from '@mui/material/Divider';\nimport FormControl from '@mui/material/FormControl';\nimport Grid from '@mui/material/Grid';\nimport TextField from '@mui/material/TextField';\nimport Tooltip from '@mui/material/Tooltip';\nimport Typography from '@mui/material/Typography';\nimport { Theme, useTheme } from '@mui/material/styles';\nimport { withStyles } from '@mui/styles';\nimport { FC, default as React, useEffect, useState } from 'react';\nimport { infraWalletApiRef } from '../../api/InfraWalletApi';\nimport { extractAccountInfo, extractProvider, getReportKeyAndValues, tagExists } from '../../api/functions';\nimport { Tag } from '../../api/types';\nimport { ProviderIcon } from '../ProviderIcon';\nimport { FiltersComponentProps } from '../types';\n\nconst icon = <CheckBoxOutlineBlankIcon fontSize=\"small\" />;\nconst checkedIcon = <CheckBoxIcon fontSize=\"small\" />;\n\nconst HtmlTooltip = withStyles((theme: Theme) => ({\n tooltip: {\n backgroundColor: '#f5f5f9',\n color: 'rgba(0, 0, 0, 0.87)',\n maxWidth: 400,\n fontSize: typeof theme.typography?.pxToRem === 'function' ? theme.typography.pxToRem(14) : '14px',\n border: '1px solid #dadde9',\n },\n}))(Tooltip);\n\nexport const FiltersComponent: FC<FiltersComponentProps> = ({\n reports,\n filters,\n monthRange,\n filtersSetter,\n selectedTags: selectedTagsProp,\n selectedTagsSetter,\n providerErrorsSetter,\n}) => {\n const theme = useTheme();\n const keyValues: { [key: string]: string[] } = getReportKeyAndValues(reports);\n\n // tag providers\n const [tagProviders, _setTagProviders] = useState<string[]>(['AWS', 'Azure']);\n const [tagProvider, setTagProvider] = useState<string>();\n\n // tag keys\n const [openTagKey, setOpenTagKey] = useState(false);\n const [tagKeys, setTagKeys] = useState<Tag[] | undefined>(undefined);\n const [selectedTagKey, setSelectedTagKey] = useState<Tag | undefined>(undefined);\n const [resetTagKeys, setResetTagKeys] = useState(false);\n const loadingTagKeys = openTagKey && tagKeys === undefined;\n\n // tag values\n const [openTagValue, setOpenTagValue] = useState(false);\n const [tagValues, setTagValues] = useState<Tag[] | undefined>(undefined);\n const [resetTagValues, setResetTagValues] = useState(false);\n const loadingTagValues = openTagValue && tagValues === undefined;\n\n // user selected tags - initialize from prop (URL-derived tags)\n const [selectedTags, setSelectedTags] = useState<Tag[]>(selectedTagsProp || []);\n\n const infraWalletApi = useApi(infraWalletApiRef);\n const alertApi = useApi(alertApiRef);\n\n const handleFiltersChange = (key: string, newValue: string[]): void => {\n const updatedFilters = { ...filters, [key]: newValue };\n filtersSetter(updatedFilters);\n };\n\n const handleTagProviderChange = (provider: string | null) => {\n setTagProvider('');\n setOpenTagKey(false);\n setResetTagKeys(prev => !prev);\n setTagKeys(undefined);\n setSelectedTagKey(undefined);\n setOpenTagValue(false);\n setTagValues([]);\n\n if (provider) {\n setTagProvider(provider);\n setOpenTagKey(true);\n\n // Automatically add provider filter when Tag Provider is selected\n const currentProviderFilters = filters.provider || [];\n if (!currentProviderFilters.includes(provider)) {\n handleFiltersChange('provider', [...currentProviderFilters, provider]);\n }\n }\n };\n\n const handleTagKeyChange = (tagKey: Tag | string | null) => {\n setSelectedTagKey(undefined);\n setTagValues(undefined);\n setResetTagValues(prev => !prev);\n\n if (typeof tagKey === 'string') {\n return;\n }\n\n if (tagKey) {\n setSelectedTagKey(tagKey);\n setOpenTagValue(true);\n }\n };\n\n const handleTagValueSelection = (tag: Tag | string | null) => {\n if (typeof tag === 'string') {\n return;\n }\n\n if (tag && !tagExists(selectedTags, tag)) {\n setResetTagValues(prev => !prev);\n setSelectedTags([...selectedTags, tag]);\n }\n };\n\n const handleDeleteTag = (tagToDelete: Tag) => () => {\n setSelectedTags(\n selectedTags.filter(\n tag =>\n !(tag.provider === tagToDelete.provider && tag.key === tagToDelete.key && tag.value === tagToDelete.value),\n ),\n );\n };\n\n useEffect(() => {\n if (!loadingTagKeys) {\n return;\n }\n\n (async () => {\n if (tagProvider) {\n await infraWalletApi\n .getTagKeys(tagProvider, monthRange.startMonth, monthRange.endMonth)\n .then(response => {\n if (response.data) {\n setTagKeys(response.data);\n }\n if (response.status === 207 && response.errors) {\n providerErrorsSetter(response.errors);\n }\n })\n .catch(e => alertApi.post({ message: `${e.message}`, severity: 'error' }));\n }\n })();\n }, [loadingTagKeys, tagProvider, monthRange, infraWalletApi, alertApi, providerErrorsSetter]);\n\n useEffect(() => {\n if (!loadingTagValues) {\n return;\n }\n\n (async () => {\n if (selectedTagKey) {\n await infraWalletApi\n .getTagValues(selectedTagKey, monthRange.startMonth, monthRange.endMonth)\n .then(response => {\n if (response.data) {\n setTagValues(response.data);\n }\n if (response.status === 207 && response.errors) {\n providerErrorsSetter(response.errors);\n }\n })\n .catch(e => alertApi.post({ message: `${e.message}`, severity: 'error' }));\n }\n })();\n }, [loadingTagValues, selectedTagKey, monthRange, infraWalletApi, alertApi, providerErrorsSetter]);\n\n return (\n <Grid container>\n <Grid item xs={12}>\n {Object.keys(keyValues).map(key => (\n <FormControl\n key={`form-${key}`}\n sx={{ marginLeft: theme.spacing(1), marginRight: theme.spacing(3), minWidth: 300 }}\n >\n <Autocomplete\n multiple\n id={`checkboxes-${key}`}\n options={keyValues[key] || []}\n value={(filters[key] || []).filter(v => (keyValues[key] || []).includes(v))}\n onChange={(_event, value: string[], _reason) => handleFiltersChange(key, value)}\n isOptionEqualToValue={(option, value) => option === value}\n disableCloseOnSelect\n renderOption={(props, option, { selected }) => {\n let provider = undefined;\n let providerIcon = undefined;\n let accountName = undefined;\n let accountId = undefined;\n if (key === 'provider') {\n provider = option;\n providerIcon = <ProviderIcon provider={provider} />;\n } else if (['account', 'service'].includes(key)) {\n provider = extractProvider(option);\n providerIcon = <ProviderIcon provider={provider} />;\n }\n\n if (key === 'account') {\n const account = extractAccountInfo(option.replace(`${provider}/`, ''));\n accountName = account.accountName;\n accountId = account.accountId;\n }\n\n return (\n <li {...props} key={option}>\n <Checkbox icon={icon} checkedIcon={checkedIcon} style={{ marginRight: 8 }} checked={selected} />\n {providerIcon && <>{providerIcon} </>}\n {key === 'account' ? (\n <div>\n <Typography variant=\"body2\">{accountName}</Typography>\n <Typography variant=\"caption\" color=\"textSecondary\">\n {accountId}\n </Typography>\n </div>\n ) : (\n <Typography variant=\"body2\">{option.replace(`${provider}/`, '')}</Typography>\n )}\n </li>\n );\n }}\n renderInput={params => (\n <TextField {...params} variant=\"standard\" label={key.charAt(0).toUpperCase() + key.slice(1)} />\n )}\n />\n </FormControl>\n ))}\n <FormControl style={{ marginTop: 10 }}>\n <Button variant=\"contained\" color=\"primary\" onClick={() => filtersSetter({})}>\n Clear filters\n </Button>\n </FormControl>\n </Grid>\n <Grid item xs={12}>\n <Divider />\n </Grid>\n <Grid item xs={12}>\n <FormControl sx={{ marginLeft: theme.spacing(1), marginRight: theme.spacing(3), minWidth: 300 }}>\n <Autocomplete\n id=\"tag-providers\"\n options={tagProviders}\n onChange={(_, provider) => handleTagProviderChange(provider)}\n renderInput={params => <TextField {...params} variant=\"standard\" label=\"Tag provider\" />}\n renderOption={(props, option) => (\n <li {...props} key={option}>\n <Typography variant=\"body2\">{option}</Typography>\n </li>\n )}\n />\n </FormControl>\n <FormControl sx={{ marginLeft: theme.spacing(1), marginRight: theme.spacing(3), minWidth: 300 }}>\n <Autocomplete\n id=\"tag-keys\"\n key={String(resetTagKeys)}\n // freeSolo\n disabled={!tagProvider}\n open={openTagKey}\n onOpen={() => setOpenTagKey(true)}\n onClose={() => setOpenTagKey(false)}\n options={tagKeys?.length ? tagKeys : [{ key: 'No value', provider: tagProvider as string }]}\n getOptionLabel={tag => tag.key}\n getOptionDisabled={tag => tag.key === 'No value'}\n loading={loadingTagKeys}\n onChange={(_, tagKey) => handleTagKeyChange(tagKey)}\n renderInput={params => (\n <TextField\n {...params}\n variant=\"standard\"\n label=\"Tag keys\"\n InputProps={{\n ...params.InputProps,\n endAdornment: (\n <React.Fragment>\n {loadingTagKeys ? <CircularProgress color=\"inherit\" size={20} /> : null}\n {params.InputProps?.endAdornment}\n </React.Fragment>\n ),\n }}\n />\n )}\n renderOption={(props, option) => (\n <li {...props} key={option.key}>\n <Typography variant=\"body2\">{option.key}</Typography>\n </li>\n )}\n />\n </FormControl>\n <FormControl sx={{ marginLeft: theme.spacing(1), marginRight: theme.spacing(3), minWidth: 300 }}>\n <Autocomplete\n id=\"tag-values\"\n key={String(resetTagValues)}\n // freeSolo\n disabled={!selectedTagKey}\n open={openTagValue}\n onOpen={() => setOpenTagValue(true)}\n onClose={() => setOpenTagValue(false)}\n options={\n tagValues?.length ? tagValues : [{ key: 'No value', value: 'No value', provider: tagProvider as string }]\n }\n getOptionLabel={tag => tag?.value || ''}\n getOptionDisabled={tag => tag?.value === 'No value' || tagExists(selectedTags, tag)}\n loading={loadingTagValues}\n onChange={(_, tag) => handleTagValueSelection(tag)}\n renderInput={params => (\n <TextField\n {...params}\n variant=\"standard\"\n label=\"Tag values\"\n InputProps={{\n ...params.InputProps,\n endAdornment: (\n <React.Fragment>\n {loadingTagValues ? <CircularProgress color=\"inherit\" size={20} /> : null}\n {params.InputProps?.endAdornment}\n </React.Fragment>\n ),\n }}\n />\n )}\n renderOption={(props, option) => (\n <li {...props} key={option.value}>\n <Typography variant=\"body2\">{option.value}</Typography>\n </li>\n )}\n />\n </FormControl>\n <FormControl style={{ marginTop: 10 }}>\n <HtmlTooltip\n title={\n <React.Fragment>\n You can apply <b>tags</b> to <em>one or more</em> providers. <b>Tags</b> will only filter the costs for\n the <b>selected providers</b>, while <em>others remain unchanged</em>.\n </React.Fragment>\n }\n >\n <Button variant=\"contained\" color=\"primary\" onClick={() => selectedTagsSetter(selectedTags)}>\n Apply\n </Button>\n </HtmlTooltip>\n </FormControl>\n </Grid>\n <Grid item xs={12}>\n {selectedTags.map(tag => (\n <Chip\n size=\"small\"\n key={`${tag.provider}/${tag.key}=${tag.value}`}\n label={`${tag.provider}/${tag.key}=${tag.value}`}\n onDelete={handleDeleteTag(tag)}\n />\n ))}\n </Grid>\n </Grid>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -12,6 +12,7 @@ import React, { useState, useCallback, useEffect } from 'react';
|
|
|
12
12
|
import { useParams } from 'react-router-dom';
|
|
13
13
|
import { infraWalletApiRef } from '../../api/InfraWalletApi.esm.js';
|
|
14
14
|
import { getPeriodStrings, filterCostReports, aggregateCostReports, mergeCostReports, getAllReportTags } from '../../api/functions.esm.js';
|
|
15
|
+
import { useInfraWalletLuceneParams } from '../../hooks/useInfraWalletLuceneParams.esm.js';
|
|
15
16
|
import { Budgets } from '../Budgets/Budgets.esm.js';
|
|
16
17
|
import { ColumnsChartComponent } from '../ColumnsChartComponent/ColumnsChartComponent.esm.js';
|
|
17
18
|
import { CostReportsTableComponent } from '../CostReportsTableComponent/CostReportsTableComponent.esm.js';
|
|
@@ -72,22 +73,31 @@ const ReportsComponent = (props) => {
|
|
|
72
73
|
}
|
|
73
74
|
const defaultShowLastXMonths = configApi.getOptionalNumber("infraWallet.settings.defaultShowLastXMonths") ?? 3;
|
|
74
75
|
const MERGE_THRESHOLD = 8;
|
|
76
|
+
const defaultMonthRange = {
|
|
77
|
+
startMonth: startOfMonth(addMonths(/* @__PURE__ */ new Date(), defaultShowLastXMonths * -1 + 1)),
|
|
78
|
+
endMonth: endOfMonth(/* @__PURE__ */ new Date())
|
|
79
|
+
};
|
|
80
|
+
const { getInitialState, updateUrlState, isInitialMount } = useInfraWalletLuceneParams({
|
|
81
|
+
defaultFilters: {},
|
|
82
|
+
defaultTags: [],
|
|
83
|
+
defaultMonthRange,
|
|
84
|
+
defaultGranularity: "monthly",
|
|
85
|
+
defaultAggregatedBy: defaultGroupBy
|
|
86
|
+
});
|
|
87
|
+
const initialState = getInitialState();
|
|
75
88
|
const [selectedView, setSelectedView] = useState("Overview");
|
|
76
|
-
const [selectedTags, setSelectedTags] = useState(
|
|
89
|
+
const [selectedTags, setSelectedTags] = useState(initialState.selectedTags);
|
|
77
90
|
const [reports, setReports] = useState(void 0);
|
|
78
91
|
const [metrics, setMetrics] = useState([]);
|
|
79
|
-
const [filters, setFilters] = useState(
|
|
92
|
+
const [filters, setFilters] = useState(initialState.filters);
|
|
80
93
|
const [cloudProviderErrors, setCloudProviderErrors] = useState([]);
|
|
81
94
|
const [reportsAggregated, setReportsAggregated] = useState(void 0);
|
|
82
95
|
const [reportsAggregatedAndMerged, setReportsAggregatedAndMerged] = useState(void 0);
|
|
83
96
|
const [reportTags, setReportTags] = useState([]);
|
|
84
|
-
const [granularity, setGranularity] = useState(
|
|
85
|
-
const [aggregatedBy, setAggregatedBy] = useState(
|
|
97
|
+
const [granularity, setGranularity] = useState(initialState.granularity);
|
|
98
|
+
const [aggregatedBy, setAggregatedBy] = useState(initialState.aggregatedBy);
|
|
86
99
|
const [groups] = useState("");
|
|
87
|
-
const [monthRange, setMonthRange] = useState(
|
|
88
|
-
startMonth: startOfMonth(addMonths(/* @__PURE__ */ new Date(), defaultShowLastXMonths * -1 + 1)),
|
|
89
|
-
endMonth: endOfMonth(/* @__PURE__ */ new Date())
|
|
90
|
-
});
|
|
100
|
+
const [monthRange, setMonthRange] = useState(initialState.monthRange);
|
|
91
101
|
const [periods, setPeriods] = useState([]);
|
|
92
102
|
const [highlightedItem, setHighlightedItem] = useState(void 0);
|
|
93
103
|
const alertApi = useApi(alertApiRef);
|
|
@@ -152,6 +162,31 @@ const ReportsComponent = (props) => {
|
|
|
152
162
|
}
|
|
153
163
|
}
|
|
154
164
|
}, [params]);
|
|
165
|
+
useEffect(() => {
|
|
166
|
+
if (!isInitialMount) {
|
|
167
|
+
updateUrlState({ filters });
|
|
168
|
+
}
|
|
169
|
+
}, [filters, updateUrlState, isInitialMount]);
|
|
170
|
+
useEffect(() => {
|
|
171
|
+
if (!isInitialMount) {
|
|
172
|
+
updateUrlState({ selectedTags });
|
|
173
|
+
}
|
|
174
|
+
}, [selectedTags, updateUrlState, isInitialMount]);
|
|
175
|
+
useEffect(() => {
|
|
176
|
+
if (!isInitialMount) {
|
|
177
|
+
updateUrlState({ monthRange });
|
|
178
|
+
}
|
|
179
|
+
}, [monthRange, updateUrlState, isInitialMount]);
|
|
180
|
+
useEffect(() => {
|
|
181
|
+
if (!isInitialMount) {
|
|
182
|
+
updateUrlState({ granularity });
|
|
183
|
+
}
|
|
184
|
+
}, [granularity, updateUrlState, isInitialMount]);
|
|
185
|
+
useEffect(() => {
|
|
186
|
+
if (!isInitialMount) {
|
|
187
|
+
updateUrlState({ aggregatedBy });
|
|
188
|
+
}
|
|
189
|
+
}, [aggregatedBy, updateUrlState, isInitialMount]);
|
|
155
190
|
return /* @__PURE__ */ React.createElement(Page, { themeId: "tool" }, /* @__PURE__ */ React.createElement(Header, { title: title ?? "InfraWallet", subtitle: subTitle ?? "" }), /* @__PURE__ */ React.createElement(
|
|
156
191
|
HeaderTabs,
|
|
157
192
|
{
|
|
@@ -176,6 +211,7 @@ const ReportsComponent = (props) => {
|
|
|
176
211
|
filters,
|
|
177
212
|
monthRange,
|
|
178
213
|
filtersSetter: setFilters,
|
|
214
|
+
selectedTags,
|
|
179
215
|
selectedTagsSetter: setSelectedTags,
|
|
180
216
|
providerErrorsSetter: setCloudProviderErrors
|
|
181
217
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ReportsComponent.esm.js","sources":["../../../src/components/ReportsComponent/ReportsComponent.tsx"],"sourcesContent":["import { Content, Header, HeaderTabs, Page } from '@backstage/core-components';\nimport { alertApiRef, configApiRef, useApi } from '@backstage/core-plugin-api';\nimport ExpandMoreIcon from '@mui/icons-material/ExpandMore';\nimport Accordion from '@mui/material/Accordion';\nimport AccordionDetails from '@mui/material/AccordionDetails';\nimport AccordionSummary from '@mui/material/AccordionSummary';\nimport Chip from '@mui/material/Chip';\nimport Grid from '@mui/material/Grid';\nimport Typography from '@mui/material/Typography';\nimport { addMonths, endOfMonth, startOfMonth } from 'date-fns';\nimport { default as React, useCallback, useEffect, useState } from 'react';\nimport { useParams } from 'react-router-dom';\nimport { infraWalletApiRef } from '../../api/InfraWalletApi';\nimport {\n aggregateCostReports,\n filterCostReports,\n getAllReportTags,\n getPeriodStrings,\n mergeCostReports,\n} from '../../api/functions';\nimport { CloudProviderError, Filters, Metric, Report, Tag } from '../../api/types';\nimport { Budgets } from '../Budgets';\nimport { ColumnsChartComponent } from '../ColumnsChartComponent';\nimport { CostReportsTableComponent } from '../CostReportsTableComponent';\nimport { CustomCostsComponent } from '../CustomCostsComponent';\nimport { ErrorsAlertComponent } from '../ErrorsAlertComponent';\nimport { FiltersComponent } from '../FiltersComponent';\nimport { PieChartComponent } from '../PieChartComponent';\nimport { SettingsComponent } from '../SettingsComponent';\nimport { TopbarComponent } from '../TopbarComponent';\nimport { MonthRange } from '../types';\n\nexport interface ReportsComponentProps {\n title?: string;\n subTitle?: string;\n}\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\nconst checkIfFiltersActivated = (filters: Filters): boolean => {\n let activated = false;\n Object.keys(filters).forEach((key: string) => {\n if (filters[key].length > 0) {\n activated = true;\n }\n });\n return activated;\n};\n\nexport const ReportsComponent = (props: ReportsComponentProps) => {\n const { title, subTitle } = props;\n const configApi = useApi(configApiRef);\n const params = useParams();\n\n let defaultGroupBy = configApi.getOptionalString('infraWallet.settings.defaultGroupBy') ?? 'none';\n const budgetsEnabled = configApi.getOptionalBoolean('infraWallet.settings.budgets.enabled') ?? true;\n const customCostsEnabled = configApi.getOptionalBoolean('infraWallet.settings.customCosts.enabled') ?? true;\n const businessMetricsEnabled = configApi.getOptionalBoolean('infraWallet.settings.businessMetrics.enabled') ?? true;\n const tabsToShow = ['Overview'];\n if (budgetsEnabled) {\n tabsToShow.push('Budgets');\n }\n if (customCostsEnabled) {\n tabsToShow.push('Custom Costs');\n }\n if (businessMetricsEnabled) {\n tabsToShow.push('Business Metrics');\n }\n // \"name\" is renamed to \"account\", make it backward compatibility\n if (defaultGroupBy === 'name') {\n defaultGroupBy = 'account';\n }\n\n const defaultShowLastXMonths = configApi.getOptionalNumber('infraWallet.settings.defaultShowLastXMonths') ?? 3;\n\n const MERGE_THRESHOLD = 8;\n\n const [selectedView, setSelectedView] = useState<string>('Overview');\n\n const [selectedTags, setSelectedTags] = useState<Tag[]>([]);\n const [reports, setReports] = useState<Report[] | undefined>(undefined);\n const [metrics, setMetrics] = useState<Metric[]>([]);\n const [filters, setFilters] = useState<Filters>({});\n const [cloudProviderErrors, setCloudProviderErrors] = useState<CloudProviderError[]>([]);\n const [reportsAggregated, setReportsAggregated] = useState<Report[] | undefined>(undefined);\n const [reportsAggregatedAndMerged, setReportsAggregatedAndMerged] = useState<Report[] | undefined>(undefined);\n const [reportTags, setReportTags] = useState<string[]>([]);\n const [granularity, setGranularity] = useState<string>('monthly');\n const [aggregatedBy, setAggregatedBy] = useState<string>(defaultGroupBy);\n const [groups] = useState<string>('');\n const [monthRange, setMonthRange] = useState<MonthRange>({\n startMonth: startOfMonth(addMonths(new Date(), defaultShowLastXMonths * -1 + 1)),\n endMonth: endOfMonth(new Date()),\n });\n const [periods, setPeriods] = useState<string[]>([]);\n const [highlightedItem, setHighlightedItem] = useState<string | undefined>(undefined);\n\n const alertApi = useApi(alertApiRef);\n const infraWalletApi = useApi(infraWalletApiRef);\n\n const fetchCostReportsCallback = useCallback(async () => {\n setReportsAggregated(undefined);\n setReportsAggregatedAndMerged(undefined);\n await infraWalletApi\n .getCostReports('', selectedTags, groups, granularity, monthRange.startMonth, monthRange.endMonth)\n .then(reportsResponse => {\n if (reportsResponse.data) {\n setReports(reportsResponse.data);\n setPeriods(getPeriodStrings(granularity, monthRange.startMonth, monthRange.endMonth));\n }\n if (reportsResponse.status === 207 && reportsResponse.errors) {\n setCloudProviderErrors(reportsResponse.errors);\n }\n })\n .catch(e => alertApi.post({ message: `${e.message}`, severity: 'error' }));\n }, [groups, monthRange, granularity, selectedTags, infraWalletApi, alertApi]);\n\n const fetchMetricsCallback = useCallback(async () => {\n await infraWalletApi\n .getMetrics(params.name ?? 'default', granularity, monthRange.startMonth, monthRange.endMonth)\n .then(metricsResponse => {\n if (metricsResponse.data && metricsResponse.data.length > 0) {\n setMetrics(metricsResponse.data);\n }\n if (metricsResponse.status === 207 && metricsResponse.errors) {\n setCloudProviderErrors(metricsResponse.errors);\n }\n })\n .catch(e => alertApi.post({ message: `${e.message}`, severity: 'error' }));\n }, [params.name, monthRange, granularity, infraWalletApi, alertApi]);\n\n useEffect(() => {\n if (reports !== undefined) {\n const filteredReports = filterCostReports(reports, filters);\n const aggregatedReports = aggregateCostReports(filteredReports, aggregatedBy);\n const aggregatedAndMergedReports = mergeCostReports(aggregatedReports, MERGE_THRESHOLD);\n const allTags = getAllReportTags(reports);\n setReportsAggregated(aggregatedReports);\n setReportsAggregatedAndMerged(aggregatedAndMergedReports);\n setReportTags(allTags);\n }\n }, [filters, reports, aggregatedBy, granularity, monthRange]);\n\n useEffect(() => {\n fetchCostReportsCallback();\n fetchMetricsCallback();\n }, [fetchCostReportsCallback, fetchMetricsCallback]);\n\n // provide a way for users to access these tabs, if they are configfured to be hidden\n useEffect(() => {\n if (params.selectedView) {\n switch (params.selectedView) {\n case 'budgets': {\n setSelectedView('Budgets');\n break;\n }\n case 'custom_costs': {\n setSelectedView('Custom Costs');\n break;\n }\n case 'business_metrics': {\n setSelectedView('Business Metrics');\n break;\n }\n default: {\n setSelectedView('Overview');\n break;\n }\n }\n }\n }, [params]);\n\n return (\n <Page themeId=\"tool\">\n <Header title={title ?? 'InfraWallet'} subtitle={subTitle ?? ''} />\n <HeaderTabs\n tabs={tabsToShow.map(tab => {\n return { id: tab, label: tab };\n })}\n onChange={index => setSelectedView(tabsToShow[index])}\n />\n <Content>\n <Grid container spacing={3}>\n {cloudProviderErrors.length > 0 && (\n <Grid item xs={12}>\n <ErrorsAlertComponent errors={cloudProviderErrors} />\n </Grid>\n )}\n {selectedView === 'Overview' && (\n <>\n <Grid item xs={12}>\n <TopbarComponent\n aggregatedBy={aggregatedBy}\n aggregatedBySetter={setAggregatedBy}\n tags={reportTags}\n monthRange={monthRange}\n monthRangeSetter={setMonthRange}\n />\n </Grid>\n <Grid item xs={12}>\n <Accordion>\n <AccordionSummary expandIcon={<ExpandMoreIcon />} aria-controls=\"filters-content\" id=\"filters-header\">\n <Typography>\n Filters {checkIfFiltersActivated(filters) && <Chip size=\"small\" label=\"active\" color=\"primary\" />}\n </Typography>\n </AccordionSummary>\n <AccordionDetails>\n <FiltersComponent\n reports={reports}\n filters={filters}\n monthRange={monthRange}\n filtersSetter={setFilters}\n selectedTagsSetter={setSelectedTags}\n providerErrorsSetter={setCloudProviderErrors}\n />\n </AccordionDetails>\n </Accordion>\n </Grid>\n <Grid item xs={12} md={4} lg={3}>\n <PieChartComponent\n categories={\n reportsAggregatedAndMerged ? reportsAggregatedAndMerged.map((item: any) => item.id) : undefined\n }\n series={\n reportsAggregatedAndMerged\n ? reportsAggregatedAndMerged.map((item: any) => getTotalCost(item))\n : undefined\n }\n height={450}\n highlightedItem={highlightedItem}\n highlightedItemSetter={setHighlightedItem}\n />\n </Grid>\n <Grid item xs={12} md={8} lg={9}>\n <ColumnsChartComponent\n granularity={granularity}\n granularitySetter={setGranularity}\n periods={periods}\n costs={\n reportsAggregatedAndMerged\n ? reportsAggregatedAndMerged.map((item: any) => ({\n name: item.id,\n data: rearrangeData(item, periods),\n }))\n : undefined\n }\n metrics={metrics.map((item: any) => ({\n name: item.name,\n group: item.group,\n data: rearrangeData(item, periods),\n }))}\n height={450}\n highlightedItem={highlightedItem}\n highlightedItemSetter={setHighlightedItem}\n />\n </Grid>\n <Grid item xs={12}>\n <CostReportsTableComponent reports={reportsAggregated} aggregatedBy={aggregatedBy} periods={periods} />\n </Grid>\n </>\n )}\n {selectedView === 'Budgets' && (\n <Grid item xs={12}>\n <Budgets providerErrorsSetter={setCloudProviderErrors} />\n </Grid>\n )}\n {selectedView === 'Custom Costs' && (\n <Grid item xs={12}>\n <CustomCostsComponent />\n </Grid>\n )}\n {selectedView === 'Business Metrics' && (\n <Grid item xs={12}>\n <SettingsComponent />\n </Grid>\n )}\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, HeaderTabs, Page } from '@backstage/core-components';\nimport { alertApiRef, configApiRef, useApi } from '@backstage/core-plugin-api';\nimport ExpandMoreIcon from '@mui/icons-material/ExpandMore';\nimport Accordion from '@mui/material/Accordion';\nimport AccordionDetails from '@mui/material/AccordionDetails';\nimport AccordionSummary from '@mui/material/AccordionSummary';\nimport Chip from '@mui/material/Chip';\nimport Grid from '@mui/material/Grid';\nimport Typography from '@mui/material/Typography';\nimport { addMonths, endOfMonth, startOfMonth } from 'date-fns';\nimport { default as React, useCallback, useEffect, useState } from 'react';\nimport { useParams } from 'react-router-dom';\nimport { infraWalletApiRef } from '../../api/InfraWalletApi';\nimport {\n aggregateCostReports,\n filterCostReports,\n getAllReportTags,\n getPeriodStrings,\n mergeCostReports,\n} from '../../api/functions';\nimport { CloudProviderError, Filters, Metric, Report, Tag } from '../../api/types';\nimport { useInfraWalletLuceneParams } from '../../hooks/useInfraWalletLuceneParams';\nimport { Budgets } from '../Budgets';\nimport { ColumnsChartComponent } from '../ColumnsChartComponent';\nimport { CostReportsTableComponent } from '../CostReportsTableComponent';\nimport { CustomCostsComponent } from '../CustomCostsComponent';\nimport { ErrorsAlertComponent } from '../ErrorsAlertComponent';\nimport { FiltersComponent } from '../FiltersComponent';\nimport { PieChartComponent } from '../PieChartComponent';\nimport { SettingsComponent } from '../SettingsComponent';\nimport { TopbarComponent } from '../TopbarComponent';\nimport { MonthRange } from '../types';\n\nexport interface ReportsComponentProps {\n title?: string;\n subTitle?: string;\n}\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\nconst checkIfFiltersActivated = (filters: Filters): boolean => {\n let activated = false;\n Object.keys(filters).forEach((key: string) => {\n if (filters[key].length > 0) {\n activated = true;\n }\n });\n return activated;\n};\n\nexport const ReportsComponent = (props: ReportsComponentProps) => {\n const { title, subTitle } = props;\n const configApi = useApi(configApiRef);\n const params = useParams();\n\n let defaultGroupBy = configApi.getOptionalString('infraWallet.settings.defaultGroupBy') ?? 'none';\n const budgetsEnabled = configApi.getOptionalBoolean('infraWallet.settings.budgets.enabled') ?? true;\n const customCostsEnabled = configApi.getOptionalBoolean('infraWallet.settings.customCosts.enabled') ?? true;\n const businessMetricsEnabled = configApi.getOptionalBoolean('infraWallet.settings.businessMetrics.enabled') ?? true;\n const tabsToShow = ['Overview'];\n if (budgetsEnabled) {\n tabsToShow.push('Budgets');\n }\n if (customCostsEnabled) {\n tabsToShow.push('Custom Costs');\n }\n if (businessMetricsEnabled) {\n tabsToShow.push('Business Metrics');\n }\n // \"name\" is renamed to \"account\", make it backward compatibility\n if (defaultGroupBy === 'name') {\n defaultGroupBy = 'account';\n }\n\n const defaultShowLastXMonths = configApi.getOptionalNumber('infraWallet.settings.defaultShowLastXMonths') ?? 3;\n\n const MERGE_THRESHOLD = 8;\n\n // Initialize URL search params hook with defaults\n const defaultMonthRange: MonthRange = {\n startMonth: startOfMonth(addMonths(new Date(), defaultShowLastXMonths * -1 + 1)),\n endMonth: endOfMonth(new Date()),\n };\n\n const { getInitialState, updateUrlState, isInitialMount } = useInfraWalletLuceneParams({\n defaultFilters: {},\n defaultTags: [],\n defaultMonthRange,\n defaultGranularity: 'monthly',\n defaultAggregatedBy: defaultGroupBy,\n });\n\n // Get initial state from URL or defaults\n const initialState = getInitialState();\n\n const [selectedView, setSelectedView] = useState<string>('Overview');\n\n const [selectedTags, setSelectedTags] = useState<Tag[]>(initialState.selectedTags);\n const [reports, setReports] = useState<Report[] | undefined>(undefined);\n const [metrics, setMetrics] = useState<Metric[]>([]);\n const [filters, setFilters] = useState<Filters>(initialState.filters);\n const [cloudProviderErrors, setCloudProviderErrors] = useState<CloudProviderError[]>([]);\n const [reportsAggregated, setReportsAggregated] = useState<Report[] | undefined>(undefined);\n const [reportsAggregatedAndMerged, setReportsAggregatedAndMerged] = useState<Report[] | undefined>(undefined);\n const [reportTags, setReportTags] = useState<string[]>([]);\n const [granularity, setGranularity] = useState<string>(initialState.granularity);\n const [aggregatedBy, setAggregatedBy] = useState<string>(initialState.aggregatedBy);\n const [groups] = useState<string>('');\n const [monthRange, setMonthRange] = useState<MonthRange>(initialState.monthRange);\n const [periods, setPeriods] = useState<string[]>([]);\n const [highlightedItem, setHighlightedItem] = useState<string | undefined>(undefined);\n\n const alertApi = useApi(alertApiRef);\n const infraWalletApi = useApi(infraWalletApiRef);\n\n const fetchCostReportsCallback = useCallback(async () => {\n setReportsAggregated(undefined);\n setReportsAggregatedAndMerged(undefined);\n await infraWalletApi\n .getCostReports('', selectedTags, groups, granularity, monthRange.startMonth, monthRange.endMonth)\n .then(reportsResponse => {\n if (reportsResponse.data) {\n setReports(reportsResponse.data);\n setPeriods(getPeriodStrings(granularity, monthRange.startMonth, monthRange.endMonth));\n }\n if (reportsResponse.status === 207 && reportsResponse.errors) {\n setCloudProviderErrors(reportsResponse.errors);\n }\n })\n .catch(e => alertApi.post({ message: `${e.message}`, severity: 'error' }));\n }, [groups, monthRange, granularity, selectedTags, infraWalletApi, alertApi]);\n\n const fetchMetricsCallback = useCallback(async () => {\n await infraWalletApi\n .getMetrics(params.name ?? 'default', granularity, monthRange.startMonth, monthRange.endMonth)\n .then(metricsResponse => {\n if (metricsResponse.data && metricsResponse.data.length > 0) {\n setMetrics(metricsResponse.data);\n }\n if (metricsResponse.status === 207 && metricsResponse.errors) {\n setCloudProviderErrors(metricsResponse.errors);\n }\n })\n .catch(e => alertApi.post({ message: `${e.message}`, severity: 'error' }));\n }, [params.name, monthRange, granularity, infraWalletApi, alertApi]);\n\n useEffect(() => {\n if (reports !== undefined) {\n const filteredReports = filterCostReports(reports, filters);\n const aggregatedReports = aggregateCostReports(filteredReports, aggregatedBy);\n const aggregatedAndMergedReports = mergeCostReports(aggregatedReports, MERGE_THRESHOLD);\n const allTags = getAllReportTags(reports);\n setReportsAggregated(aggregatedReports);\n setReportsAggregatedAndMerged(aggregatedAndMergedReports);\n setReportTags(allTags);\n }\n }, [filters, reports, aggregatedBy, granularity, monthRange]);\n\n useEffect(() => {\n fetchCostReportsCallback();\n fetchMetricsCallback();\n }, [fetchCostReportsCallback, fetchMetricsCallback]);\n\n // provide a way for users to access these tabs, if they are configfured to be hidden\n useEffect(() => {\n if (params.selectedView) {\n switch (params.selectedView) {\n case 'budgets': {\n setSelectedView('Budgets');\n break;\n }\n case 'custom_costs': {\n setSelectedView('Custom Costs');\n break;\n }\n case 'business_metrics': {\n setSelectedView('Business Metrics');\n break;\n }\n default: {\n setSelectedView('Overview');\n break;\n }\n }\n }\n }, [params]);\n\n // Sync state changes to URL (skip initial mount to avoid overwriting URL params)\n useEffect(() => {\n if (!isInitialMount) {\n updateUrlState({ filters });\n }\n }, [filters, updateUrlState, isInitialMount]);\n\n useEffect(() => {\n if (!isInitialMount) {\n updateUrlState({ selectedTags });\n }\n }, [selectedTags, updateUrlState, isInitialMount]);\n\n useEffect(() => {\n if (!isInitialMount) {\n updateUrlState({ monthRange });\n }\n }, [monthRange, updateUrlState, isInitialMount]);\n\n useEffect(() => {\n if (!isInitialMount) {\n updateUrlState({ granularity });\n }\n }, [granularity, updateUrlState, isInitialMount]);\n\n useEffect(() => {\n if (!isInitialMount) {\n updateUrlState({ aggregatedBy });\n }\n }, [aggregatedBy, updateUrlState, isInitialMount]);\n\n return (\n <Page themeId=\"tool\">\n <Header title={title ?? 'InfraWallet'} subtitle={subTitle ?? ''} />\n <HeaderTabs\n tabs={tabsToShow.map(tab => {\n return { id: tab, label: tab };\n })}\n onChange={index => setSelectedView(tabsToShow[index])}\n />\n <Content>\n <Grid container spacing={3}>\n {cloudProviderErrors.length > 0 && (\n <Grid item xs={12}>\n <ErrorsAlertComponent errors={cloudProviderErrors} />\n </Grid>\n )}\n {selectedView === 'Overview' && (\n <>\n <Grid item xs={12}>\n <TopbarComponent\n aggregatedBy={aggregatedBy}\n aggregatedBySetter={setAggregatedBy}\n tags={reportTags}\n monthRange={monthRange}\n monthRangeSetter={setMonthRange}\n />\n </Grid>\n <Grid item xs={12}>\n <Accordion>\n <AccordionSummary expandIcon={<ExpandMoreIcon />} aria-controls=\"filters-content\" id=\"filters-header\">\n <Typography>\n Filters {checkIfFiltersActivated(filters) && <Chip size=\"small\" label=\"active\" color=\"primary\" />}\n </Typography>\n </AccordionSummary>\n <AccordionDetails>\n <FiltersComponent\n reports={reports}\n filters={filters}\n monthRange={monthRange}\n filtersSetter={setFilters}\n selectedTags={selectedTags}\n selectedTagsSetter={setSelectedTags}\n providerErrorsSetter={setCloudProviderErrors}\n />\n </AccordionDetails>\n </Accordion>\n </Grid>\n <Grid item xs={12} md={4} lg={3}>\n <PieChartComponent\n categories={\n reportsAggregatedAndMerged ? reportsAggregatedAndMerged.map((item: any) => item.id) : undefined\n }\n series={\n reportsAggregatedAndMerged\n ? reportsAggregatedAndMerged.map((item: any) => getTotalCost(item))\n : undefined\n }\n height={450}\n highlightedItem={highlightedItem}\n highlightedItemSetter={setHighlightedItem}\n />\n </Grid>\n <Grid item xs={12} md={8} lg={9}>\n <ColumnsChartComponent\n granularity={granularity}\n granularitySetter={setGranularity}\n periods={periods}\n costs={\n reportsAggregatedAndMerged\n ? reportsAggregatedAndMerged.map((item: any) => ({\n name: item.id,\n data: rearrangeData(item, periods),\n }))\n : undefined\n }\n metrics={metrics.map((item: any) => ({\n name: item.name,\n group: item.group,\n data: rearrangeData(item, periods),\n }))}\n height={450}\n highlightedItem={highlightedItem}\n highlightedItemSetter={setHighlightedItem}\n />\n </Grid>\n <Grid item xs={12}>\n <CostReportsTableComponent reports={reportsAggregated} aggregatedBy={aggregatedBy} periods={periods} />\n </Grid>\n </>\n )}\n {selectedView === 'Budgets' && (\n <Grid item xs={12}>\n <Budgets providerErrorsSetter={setCloudProviderErrors} />\n </Grid>\n )}\n {selectedView === 'Custom Costs' && (\n <Grid item xs={12}>\n <CustomCostsComponent />\n </Grid>\n )}\n {selectedView === 'Business Metrics' && (\n <Grid item xs={12}>\n <SettingsComponent />\n </Grid>\n )}\n </Grid>\n </Content>\n </Page>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { startOfMonth, parse, format } from 'date-fns';
|
|
2
|
+
import * as lucene from 'lucene';
|
|
3
|
+
import { useRef, useCallback, useEffect } from 'react';
|
|
4
|
+
import { useSearchParams } from 'react-router-dom';
|
|
5
|
+
|
|
6
|
+
const parseTag = (tagValue) => {
|
|
7
|
+
if (tagValue.includes(".") && tagValue.includes("=")) {
|
|
8
|
+
const [providerKey, value] = tagValue.split("=");
|
|
9
|
+
const [provider, key] = providerKey.split(".");
|
|
10
|
+
if (provider && key && value) {
|
|
11
|
+
return { provider, key, value };
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
if (tagValue.includes(":")) {
|
|
15
|
+
const tagParts = tagValue.split(":");
|
|
16
|
+
if (tagParts.length >= 3) {
|
|
17
|
+
const provider = tagParts[0];
|
|
18
|
+
const key = tagParts[1];
|
|
19
|
+
const value = tagParts.slice(2).join(":");
|
|
20
|
+
return { provider, key, value };
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return null;
|
|
24
|
+
};
|
|
25
|
+
const addFilterValue = (filters, field, value) => {
|
|
26
|
+
if (!filters[field]) {
|
|
27
|
+
filters[field] = [];
|
|
28
|
+
}
|
|
29
|
+
if (!filters[field].includes(value)) {
|
|
30
|
+
filters[field].push(value);
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
const astToFiltersAndTags = (ast) => {
|
|
34
|
+
const filters = {};
|
|
35
|
+
const tags = [];
|
|
36
|
+
const traverseAST = (node) => {
|
|
37
|
+
if (!node) return;
|
|
38
|
+
if (node.field && node.term) {
|
|
39
|
+
if (node.field === "tag") {
|
|
40
|
+
const tag = parseTag(node.term);
|
|
41
|
+
if (tag) {
|
|
42
|
+
tags.push(tag);
|
|
43
|
+
}
|
|
44
|
+
} else {
|
|
45
|
+
addFilterValue(filters, node.field, node.term);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
if (node.left) traverseAST(node.left);
|
|
49
|
+
if (node.right) traverseAST(node.right);
|
|
50
|
+
};
|
|
51
|
+
traverseAST(ast);
|
|
52
|
+
return { filters, tags };
|
|
53
|
+
};
|
|
54
|
+
const quoteLuceneValue = (value) => {
|
|
55
|
+
const specialChars = /[/()[\]{}\s:]/;
|
|
56
|
+
if (specialChars.test(value)) {
|
|
57
|
+
const escapedQuote = String.raw`\"`;
|
|
58
|
+
return `"${value.replaceAll('"', escapedQuote)}"`;
|
|
59
|
+
}
|
|
60
|
+
return value;
|
|
61
|
+
};
|
|
62
|
+
const quoteTag = (provider, key, value) => {
|
|
63
|
+
const specialChars = /[/()[\]{}\s:]/;
|
|
64
|
+
const tag = `${provider}.${key}=${value}`;
|
|
65
|
+
if (specialChars.test(key)) {
|
|
66
|
+
return `tag:"${tag}"`;
|
|
67
|
+
}
|
|
68
|
+
return `tag:${tag}`;
|
|
69
|
+
};
|
|
70
|
+
const filtersAndTagsToLucene = (filters, tags) => {
|
|
71
|
+
const queryParts = [];
|
|
72
|
+
for (const field of Object.keys(filters)) {
|
|
73
|
+
const values = filters[field];
|
|
74
|
+
if (values && values.length > 0) {
|
|
75
|
+
if (values.length === 1) {
|
|
76
|
+
queryParts.push(`${field}:${quoteLuceneValue(values[0])}`);
|
|
77
|
+
} else {
|
|
78
|
+
const orValues = values.map((value) => `${field}:${quoteLuceneValue(value)}`).join(" OR ");
|
|
79
|
+
queryParts.push(`(${orValues})`);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
for (const tag of tags) {
|
|
84
|
+
if (tag.provider && tag.key && tag.value) {
|
|
85
|
+
queryParts.push(quoteTag(tag.provider, tag.key, tag.value));
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return queryParts.join(" AND ");
|
|
89
|
+
};
|
|
90
|
+
const parseLuceneQuery = (query) => {
|
|
91
|
+
if (!query.trim()) {
|
|
92
|
+
return { filters: {}, tags: [] };
|
|
93
|
+
}
|
|
94
|
+
try {
|
|
95
|
+
const ast = lucene.parse(query);
|
|
96
|
+
return astToFiltersAndTags(ast);
|
|
97
|
+
} catch {
|
|
98
|
+
return { filters: {}, tags: [] };
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
const formatDateForUrl = (date) => {
|
|
102
|
+
return format(date, "yyyy-MM");
|
|
103
|
+
};
|
|
104
|
+
const parseDateFromUrl = (dateStr) => {
|
|
105
|
+
try {
|
|
106
|
+
return startOfMonth(parse(dateStr, "yyyy-MM", /* @__PURE__ */ new Date()));
|
|
107
|
+
} catch {
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
const useInfraWalletLuceneParams = (options = {}) => {
|
|
112
|
+
const [searchParams, setSearchParams] = useSearchParams();
|
|
113
|
+
const isInitialMount = useRef(true);
|
|
114
|
+
const getInitialState = useCallback(() => {
|
|
115
|
+
const queryParam = searchParams.get("q") || "";
|
|
116
|
+
const decodedQuery = decodeURIComponent(queryParam);
|
|
117
|
+
const { filters, tags } = parseLuceneQuery(decodedQuery);
|
|
118
|
+
const finalFilters = Object.keys(filters).length > 0 ? filters : options.defaultFilters || {};
|
|
119
|
+
const selectedTags = tags.length > 0 ? tags : options.defaultTags || [];
|
|
120
|
+
const fromParam = searchParams.get("from");
|
|
121
|
+
const toParam = searchParams.get("to");
|
|
122
|
+
let monthRange = options.defaultMonthRange;
|
|
123
|
+
if (fromParam && toParam) {
|
|
124
|
+
const startMonth = parseDateFromUrl(fromParam);
|
|
125
|
+
const endMonth = parseDateFromUrl(toParam);
|
|
126
|
+
if (startMonth && endMonth) {
|
|
127
|
+
monthRange = { startMonth, endMonth };
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
if (!monthRange) {
|
|
131
|
+
const currentMonth = startOfMonth(/* @__PURE__ */ new Date());
|
|
132
|
+
monthRange = { startMonth: currentMonth, endMonth: currentMonth };
|
|
133
|
+
}
|
|
134
|
+
const granularityParam = searchParams.get("granularity");
|
|
135
|
+
const granularity = granularityParam || options.defaultGranularity || "monthly";
|
|
136
|
+
const groupByParam = searchParams.get("groupBy");
|
|
137
|
+
const aggregatedBy = groupByParam || options.defaultAggregatedBy || "none";
|
|
138
|
+
return {
|
|
139
|
+
filters: finalFilters,
|
|
140
|
+
selectedTags,
|
|
141
|
+
monthRange,
|
|
142
|
+
granularity,
|
|
143
|
+
aggregatedBy
|
|
144
|
+
};
|
|
145
|
+
}, [searchParams, options]);
|
|
146
|
+
const updateUrlState = useCallback(
|
|
147
|
+
(state) => {
|
|
148
|
+
setSearchParams(
|
|
149
|
+
(prev) => {
|
|
150
|
+
const newParams = new URLSearchParams(prev);
|
|
151
|
+
if (state.filters !== void 0 || state.selectedTags !== void 0) {
|
|
152
|
+
const currentQuery = prev.get("q") || "";
|
|
153
|
+
const decodedCurrentQuery = decodeURIComponent(currentQuery);
|
|
154
|
+
const { filters: currentFilters, tags: currentTags } = parseLuceneQuery(decodedCurrentQuery);
|
|
155
|
+
const finalFilters = state.filters ?? currentFilters;
|
|
156
|
+
const finalTags = state.selectedTags ?? currentTags;
|
|
157
|
+
const luceneQuery = filtersAndTagsToLucene(finalFilters, finalTags);
|
|
158
|
+
if (luceneQuery) {
|
|
159
|
+
newParams.set("q", encodeURIComponent(luceneQuery));
|
|
160
|
+
} else {
|
|
161
|
+
newParams.delete("q");
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
if (state.monthRange !== void 0) {
|
|
165
|
+
newParams.set("from", formatDateForUrl(state.monthRange.startMonth));
|
|
166
|
+
newParams.set("to", formatDateForUrl(state.monthRange.endMonth));
|
|
167
|
+
}
|
|
168
|
+
if (state.granularity !== void 0) {
|
|
169
|
+
newParams.set("granularity", state.granularity);
|
|
170
|
+
}
|
|
171
|
+
if (state.aggregatedBy !== void 0) {
|
|
172
|
+
newParams.set("groupBy", state.aggregatedBy);
|
|
173
|
+
}
|
|
174
|
+
return newParams;
|
|
175
|
+
},
|
|
176
|
+
{ replace: true }
|
|
177
|
+
);
|
|
178
|
+
},
|
|
179
|
+
[setSearchParams]
|
|
180
|
+
);
|
|
181
|
+
useEffect(() => {
|
|
182
|
+
isInitialMount.current = false;
|
|
183
|
+
}, []);
|
|
184
|
+
return {
|
|
185
|
+
getInitialState,
|
|
186
|
+
updateUrlState,
|
|
187
|
+
isInitialMount: isInitialMount.current
|
|
188
|
+
};
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
export { useInfraWalletLuceneParams };
|
|
192
|
+
//# sourceMappingURL=useInfraWalletLuceneParams.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useInfraWalletLuceneParams.esm.js","sources":["../../src/hooks/useInfraWalletLuceneParams.ts"],"sourcesContent":["import { format, parse, startOfMonth } from 'date-fns';\nimport * as lucene from 'lucene';\nimport { useCallback, useEffect, useRef } from 'react';\nimport { useSearchParams } from 'react-router-dom';\nimport { Filters, Tag } from '../api/types';\nimport { MonthRange } from '../components/types';\n\n/**\n * Parse tag value into Tag object\n * Supports two formats:\n * 1. provider.key=value (preferred)\n * 2. provider:key:value (fallback)\n */\nconst parseTag = (tagValue: string): Tag | null => {\n // Try provider.key=value format first\n if (tagValue.includes('.') && tagValue.includes('=')) {\n const [providerKey, value] = tagValue.split('=');\n const [provider, key] = providerKey.split('.');\n if (provider && key && value) {\n return { provider, key, value };\n }\n }\n\n // Fallback to provider:key:value format\n if (tagValue.includes(':')) {\n const tagParts = tagValue.split(':');\n if (tagParts.length >= 3) {\n const provider = tagParts[0];\n const key = tagParts[1];\n const value = tagParts.slice(2).join(':'); // In case value contains colons\n return { provider, key, value };\n }\n }\n\n return null;\n};\n\n/**\n * Add a filter value to the filters object, avoiding duplicates\n */\nconst addFilterValue = (filters: Filters, field: string, value: string): void => {\n if (!filters[field]) {\n filters[field] = [];\n }\n if (!filters[field].includes(value)) {\n filters[field].push(value);\n }\n};\n\n/**\n * Convert Lucene AST to Filters and Tags\n */\nconst astToFiltersAndTags = (ast: any): { filters: Filters; tags: Tag[] } => {\n const filters: Filters = {};\n const tags: Tag[] = [];\n\n const traverseAST = (node: any): void => {\n if (!node) return;\n\n // Process field:value pairs\n if (node.field && node.term) {\n if (node.field === 'tag') {\n const tag = parseTag(node.term);\n if (tag) {\n tags.push(tag);\n }\n } else {\n addFilterValue(filters, node.field, node.term);\n }\n }\n\n // Recursively process left and right nodes\n if (node.left) traverseAST(node.left);\n if (node.right) traverseAST(node.right);\n };\n\n traverseAST(ast);\n return { filters, tags };\n};\n\n/**\n * Escape and quote a value for Lucene query if it contains special characters\n */\nconst quoteLuceneValue = (value: string): string => {\n // Check if value contains special Lucene characters that require quoting\n const specialChars = /[/()[\\]{}\\s:]/;\n if (specialChars.test(value)) {\n // Escape any quotes in the value and wrap in quotes\n const escapedQuote = String.raw`\\\"`;\n return `\"${value.replaceAll('\"', escapedQuote)}\"`;\n }\n return value;\n};\n\n/**\n * Quote a tag for Lucene query if a key contains special characters\n */\nconst quoteTag = (provider: string, key: string, value: string): string => {\n const specialChars = /[/()[\\]{}\\s:]/;\n const tag = `${provider}.${key}=${value}`;\n\n // If tag has special character in the key, it needs to be quoted. E.g. tag:\"AWS.key:environment=staging\"\n if (specialChars.test(key)) {\n return `tag:\"${tag}\"`;\n }\n return `tag:${tag}`;\n};\n\n/**\n * Convert Filters and Tags to Lucene query string\n */\nconst filtersAndTagsToLucene = (filters: Filters, tags: Tag[]): string => {\n const queryParts: string[] = [];\n\n // Convert filters to query parts\n for (const field of Object.keys(filters)) {\n const values = filters[field];\n if (values && values.length > 0) {\n if (values.length === 1) {\n queryParts.push(`${field}:${quoteLuceneValue(values[0])}`);\n } else {\n const orValues = values.map(value => `${field}:${quoteLuceneValue(value)}`).join(' OR ');\n queryParts.push(`(${orValues})`);\n }\n }\n }\n\n // Convert tags to query parts\n for (const tag of tags) {\n if (tag.provider && tag.key && tag.value) {\n // Use the new format: tag:provider.key=value\n queryParts.push(quoteTag(tag.provider, tag.key, tag.value));\n }\n }\n\n return queryParts.join(' AND ');\n};\n\n/**\n * Parse Lucene query string safely\n */\nconst parseLuceneQuery = (query: string): { filters: Filters; tags: Tag[] } => {\n if (!query.trim()) {\n return { filters: {}, tags: [] };\n }\n\n try {\n const ast = lucene.parse(query);\n return astToFiltersAndTags(ast);\n } catch {\n // Intentionally catch and ignore parse errors - invalid Lucene queries\n // should gracefully fall back to empty state rather than break the UI\n return { filters: {}, tags: [] };\n }\n};\n\n/**\n * Format date to YYYY-MM for URL\n */\nconst formatDateForUrl = (date: Date): string => {\n return format(date, 'yyyy-MM');\n};\n\n/**\n * Parse YYYY-MM from URL to Date\n */\nconst parseDateFromUrl = (dateStr: string): Date | null => {\n try {\n return startOfMonth(parse(dateStr, 'yyyy-MM', new Date()));\n } catch {\n return null;\n }\n};\n\nexport interface InfraWalletLuceneUrlState {\n filters: Filters;\n selectedTags: Tag[];\n monthRange: MonthRange;\n granularity: string;\n aggregatedBy: string;\n}\n\ninterface UseInfraWalletLuceneParamsOptions {\n defaultFilters?: Filters;\n defaultTags?: Tag[];\n defaultMonthRange?: MonthRange;\n defaultGranularity?: string;\n defaultAggregatedBy?: string;\n}\n\n/**\n * Custom hook to manage InfraWallet state in URL search params using Lucene query syntax\n * This enables deep linking and bookmarking of specific filter/view combinations\n */\nexport const useInfraWalletLuceneParams = (options: UseInfraWalletLuceneParamsOptions = {}) => {\n const [searchParams, setSearchParams] = useSearchParams();\n const isInitialMount = useRef(true);\n\n /**\n * Get initial state from URL or use defaults\n */\n const getInitialState = useCallback((): InfraWalletLuceneUrlState => {\n // Parse Lucene query (URL decode first)\n const queryParam = searchParams.get('q') || '';\n const decodedQuery = decodeURIComponent(queryParam);\n const { filters, tags } = parseLuceneQuery(decodedQuery);\n\n // Use parsed values or defaults\n const finalFilters = Object.keys(filters).length > 0 ? filters : options.defaultFilters || {};\n const selectedTags = tags.length > 0 ? tags : options.defaultTags || [];\n\n // Month Range\n const fromParam = searchParams.get('from');\n const toParam = searchParams.get('to');\n let monthRange = options.defaultMonthRange;\n if (fromParam && toParam) {\n const startMonth = parseDateFromUrl(fromParam);\n const endMonth = parseDateFromUrl(toParam);\n if (startMonth && endMonth) {\n monthRange = { startMonth, endMonth };\n }\n }\n\n // Ensure monthRange is never undefined - provide a default\n if (!monthRange) {\n const currentMonth = startOfMonth(new Date());\n monthRange = { startMonth: currentMonth, endMonth: currentMonth };\n }\n\n // Granularity\n const granularityParam = searchParams.get('granularity');\n const granularity = granularityParam || options.defaultGranularity || 'monthly';\n\n const groupByParam = searchParams.get('groupBy');\n const aggregatedBy = groupByParam || options.defaultAggregatedBy || 'none';\n\n return {\n filters: finalFilters,\n selectedTags,\n monthRange,\n granularity,\n aggregatedBy,\n };\n }, [searchParams, options]);\n\n /**\n * Update URL search params with current state\n */\n const updateUrlState = useCallback(\n (state: Partial<InfraWalletLuceneUrlState>) => {\n setSearchParams(\n prev => {\n const newParams = new URLSearchParams(prev);\n\n // Update Lucene query if filters or tags changed\n if (state.filters !== undefined || state.selectedTags !== undefined) {\n // Get current state to merge with new state\n const currentQuery = prev.get('q') || '';\n const decodedCurrentQuery = decodeURIComponent(currentQuery);\n const { filters: currentFilters, tags: currentTags } = parseLuceneQuery(decodedCurrentQuery);\n\n const finalFilters = state.filters ?? currentFilters;\n const finalTags = state.selectedTags ?? currentTags;\n\n const luceneQuery = filtersAndTagsToLucene(finalFilters, finalTags);\n if (luceneQuery) {\n // URL encode the query before setting it\n newParams.set('q', encodeURIComponent(luceneQuery));\n } else {\n newParams.delete('q');\n }\n }\n\n // Update month range\n if (state.monthRange !== undefined) {\n newParams.set('from', formatDateForUrl(state.monthRange.startMonth));\n newParams.set('to', formatDateForUrl(state.monthRange.endMonth));\n }\n\n // Update granularity\n if (state.granularity !== undefined) {\n newParams.set('granularity', state.granularity);\n }\n\n // Update aggregatedBy (groupBy)\n if (state.aggregatedBy !== undefined) {\n newParams.set('groupBy', state.aggregatedBy);\n }\n\n return newParams;\n },\n { replace: true },\n ); // Use replace to avoid creating excessive history entries\n },\n [setSearchParams],\n );\n\n useEffect(() => {\n isInitialMount.current = false;\n }, []);\n\n return {\n getInitialState,\n updateUrlState,\n isInitialMount: isInitialMount.current,\n };\n};\n"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@electrolux-oss/plugin-infrawallet",
|
|
3
|
-
"version": "1.1.0-
|
|
3
|
+
"version": "1.1.0-20251202133007-1005ef9",
|
|
4
4
|
"backstage": {
|
|
5
5
|
"role": "frontend-plugin",
|
|
6
6
|
"pluginId": "infrawallet",
|
|
@@ -54,6 +54,7 @@
|
|
|
54
54
|
"@types/react": "^18",
|
|
55
55
|
"date-fns": "2.30.0",
|
|
56
56
|
"lodash": "^4.17.21",
|
|
57
|
+
"lucene": "^2.1.1",
|
|
57
58
|
"moment": "2.30.1",
|
|
58
59
|
"mui-modal-provider": "2.2.0",
|
|
59
60
|
"node-fetch": "^2.6.7",
|
|
@@ -70,6 +71,7 @@
|
|
|
70
71
|
"@testing-library/react": "^14.0.0",
|
|
71
72
|
"@testing-library/user-event": "^14.0.0",
|
|
72
73
|
"@types/lodash": "^4.14.151",
|
|
74
|
+
"@types/lucene": "^2",
|
|
73
75
|
"@types/node-fetch": "^2.6.4",
|
|
74
76
|
"@types/react-date-range": "1.4.5",
|
|
75
77
|
"@types/uuid": "10.0.0",
|