@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.
@@ -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 && !filters[key].includes(report[key])) {
47
- match = false;
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":";;;;AAKO,MAAM,gBAAA,GAAmB,CAAC,OAAA,EAAmB,SAAA,KAAiC;AACnF,EAAA,MAAM,aAA8C,EAAC;AACrD,EAAA,OAAA,CAAQ,QAAQ,CAAA,MAAA,KAAU;AACxB,IAAA,IAAI,KAAA,GAAQ,CAAA;AACZ,IAAA,MAAA,CAAO,MAAA,CAAO,MAAA,CAAO,OAAO,CAAA,CAAE,QAAQ,CAAA,CAAA,KAAK;AACzC,MAAA,KAAA,IAAS,CAAA;AAAA,KACV,CAAA;AACD,IAAA,UAAA,CAAW,KAAK,EAAE,EAAA,EAAI,MAAA,CAAO,EAAA,EAAI,OAAc,CAAA;AAAA,GAChD,CAAA;AACD,EAAA,UAAA,CAAW,KAAK,CAAC,CAAA,EAAG,MAAM,CAAA,CAAE,KAAA,GAAQ,EAAE,KAAK,CAAA;AAC3C,EAAA,MAAM,WAAA,GAAc,WAAW,KAAA,CAAM,CAAA,EAAG,SAAS,CAAA,CAAE,GAAA,CAAI,CAAA,CAAA,KAAK,CAAA,CAAE,EAAE,CAAA;AAEhE,EAAA,MAAM,aAAA,GAAgB,MAAA;AAAA,IACpB,OAAA;AAAA,IACA,CAAC,aAAwC,MAAA,KAAW;AAClD,MAAA,IAAI,OAAA,GAAU,QAAA;AACd,MAAA,IAAI,WAAA,CAAY,QAAA,CAAS,MAAA,CAAO,EAAE,CAAA,EAAG;AACnC,QAAA,OAAA,GAAU,MAAA,CAAO,EAAA;AAAA;AAEnB,MAAA,IAAI,CAAC,WAAA,CAAY,OAAO,CAAA,EAAG;AACzB,QAAA,WAAA,CAAY,OAAO,CAAA,GAAI;AAAA,UACrB,EAAA,EAAI,OAAA;AAAA,UACJ,SAAS;AAAC,SACZ;AAAA;AAGF,MAAA,MAAA,CAAO,IAAA,CAAK,MAAA,CAAO,OAAO,CAAA,CAAE,QAAQ,CAAA,GAAA,KAAO;AACzC,QAAA,IAAI,WAAA,CAAY,OAAO,CAAA,CAAE,OAAA,CAAQ,GAAG,CAAA,EAAG;AACrC,UAAA,WAAA,CAAY,OAAO,CAAA,CAAE,OAAA,CAAQ,GAAG,CAAA,IAAK,MAAA,CAAO,QAAQ,GAAG,CAAA;AAAA,SACzD,MAAO;AACL,UAAA,WAAA,CAAY,OAAO,CAAA,CAAE,OAAA,CAAQ,GAAG,CAAA,GAAI,MAAA,CAAO,QAAQ,GAAG,CAAA;AAAA;AACxD,OACD,CAAA;AACD,MAAA,OAAO,WAAA;AAAA,KACT;AAAA,IACA;AAAC,GACH;AAEA,EAAA,OAAO,MAAA,CAAO,MAAA,CAAO,aAAa,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,CAAA,CAAE,EAAA,CAAG,aAAA,CAAc,CAAA,CAAE,EAAE,CAAC,CAAA;AAC7E;AAEO,MAAM,iBAAA,GAAoB,CAAC,OAAA,EAAmB,OAAA,KAA+B;AAClF,EAAA,MAAM,eAAA,GAAkB,OAAA,CAAQ,MAAA,CAAO,CAAA,MAAA,KAAU;AAC/C,IAAA,IAAI,KAAA,GAAQ,IAAA;AACZ,IAAA,MAAA,CAAO,IAAA,CAAK,OAAO,CAAA,CAAE,OAAA,CAAQ,CAAA,GAAA,KAAO;AAClC,MAAA,IAAI,OAAA,CAAQ,GAAG,CAAA,CAAE,MAAA,GAAS,CAAA,EAAG;AAC3B,QAAA,MAAM,WAAA,GAAc,OAAO,GAAG,CAAA;AAG9B,QAAA,IAAI,gBAAgB,MAAA,EAAW;AAC7B,UAAA,KAAA,GAAQ,KAAA;AACR,UAAA;AAAA;AAIF,QAAA,MAAM,YAAA,GAAe,OAAA,CAAQ,GAAG,CAAA,CAAE,KAAK,CAAA,WAAA,KAAe;AAEpD,UAAA,IAAI,gBAAgB,WAAA,EAAa;AAC/B,YAAA,OAAO,IAAA;AAAA;AAKT,UAAA,IAAI,QAAQ,SAAA,EAAW;AAErB,YAAA,MAAM,eAAA,GAAkB,WAAA,CAAY,KAAA,CAAM,IAAI,EAAE,CAAC,CAAA;AACjD,YAAA,MAAM,iBAAA,GAAoB,WAAA,CAAY,KAAA,CAAM,IAAI,EAAE,CAAC,CAAA;AACnD,YAAA,IAAI,oBAAoB,iBAAA,EAAmB;AACzC,cAAA,OAAO,IAAA;AAAA;AACT;AAKF,UAAA,IAAI,GAAA,KAAQ,aAAa,WAAA,CAAY,QAAA,CAAS,GAAG,CAAA,IAAK,WAAA,CAAY,QAAA,CAAS,GAAG,CAAA,EAAG;AAC/E,YAAA,OAAO,WAAA,KAAgB,WAAA;AAAA;AAGzB,UAAA,OAAO,KAAA;AAAA,SACR,CAAA;AAED,QAAA,IAAI,CAAC,YAAA,EAAc;AACjB,UAAA,KAAA,GAAQ,KAAA;AAAA;AACV;AACF,KACD,CAAA;AACD,IAAA,OAAO,KAAA;AAAA,GACR,CAAA;AAED,EAAA,OAAO,eAAA;AACT;AAEO,MAAM,oBAAA,GAAuB,CAAC,OAAA,EAAmB,YAAA,KAAoC;AAC1F,EAAA,MAAM,iBAAA,GAA+C,MAAA;AAAA,IACnD,OAAA;AAAA,IACA,CAAC,aAAa,MAAA,KAAW;AACvB,MAAA,IAAI,OAAA,GAAkB,UAAA;AACtB,MAAA,IAAI,YAAA,IAAgB,gBAAgB,MAAA,EAAQ;AAC1C,QAAA,OAAA,GAAU,OAAO,YAAY,CAAA;AAAA,OAC/B,MAAA,IAAW,iBAAiB,MAAA,EAAQ;AAClC,QAAA,OAAA,GAAU,OAAA;AAAA;AAGZ,MAAA,IAAI,CAAC,WAAA,CAAY,OAAO,CAAA,EAAG;AACzB,QAAA,WAAA,CAAY,OAAO,CAAA,GAAI;AAAA,UACrB,EAAA,EAAI,OAAA;AAAA,UACJ,UAAU,MAAA,CAAO,QAAA;AAAA,UACjB,SAAS;AAAC,SACZ;AAMA,QAAA,IAAI,iBAAiB,MAAA,EAAW;AAC9B,UAAA,WAAA,CAAY,OAAO,CAAA,CAAE,YAAY,CAAA,GAAI,OAAA;AAAA;AACvC;AAGF,MAAA,MAAA,CAAO,IAAA,CAAK,MAAA,CAAO,OAAO,CAAA,CAAE,QAAQ,CAAA,GAAA,KAAO;AACzC,QAAA,IAAI,WAAA,CAAY,OAAO,CAAA,CAAE,OAAA,CAAQ,GAAG,CAAA,EAAG;AACrC,UAAA,WAAA,CAAY,OAAO,CAAA,CAAE,OAAA,CAAQ,GAAG,CAAA,IAAK,MAAA,CAAO,QAAQ,GAAG,CAAA;AAAA,SACzD,MAAO;AACL,UAAA,WAAA,CAAY,OAAO,CAAA,CAAE,OAAA,CAAQ,GAAG,CAAA,GAAI,MAAA,CAAO,QAAQ,GAAG,CAAA;AAAA;AACxD,OACD,CAAA;AACD,MAAA,OAAO,WAAA;AAAA,KACT;AAAA,IACA;AAAC,GACH;AACA,EAAA,OAAO,MAAA,CAAO,OAAO,iBAAiB,CAAA;AACxC;AAEO,MAAM,qBAAA,GAAwB,CAAC,OAAA,KAA+D;AACnG,EAAA,MAAM,YAAA,GAAe,CAAC,IAAA,EAAM,SAAS,CAAA;AACrC,EAAA,MAAM,eAA+C,EAAC;AACtD,EAAA,OAAA,EAAS,QAAQ,CAAA,MAAA,KAAU;AACzB,IAAA,MAAA,CAAO,IAAA,CAAK,MAAM,CAAA,CAAE,OAAA,CAAQ,CAAA,GAAA,KAAO;AACjC,MAAA,IAAI,CAAC,YAAA,CAAa,QAAA,CAAS,GAAG,CAAA,EAAG;AAC/B,QAAA,IAAI,YAAA,CAAa,GAAG,CAAA,KAAM,MAAA,EAAW;AACnC,UAAA,YAAA,CAAa,GAAG,CAAA,mBAAI,IAAI,GAAA,EAAY;AAAA;AAGtC,QAAA,YAAA,CAAa,GAAG,CAAA,CAAE,GAAA,CAAI,MAAA,CAAO,GAAG,CAAW,CAAA;AAAA;AAC7C,KACD,CAAA;AAAA,GACF,CAAA;AAED,EAAA,MAAM,YAAyC,EAAC;AAChD,EAAA,MAAA,CAAO,IAAA,CAAK,YAAY,CAAA,CAAE,OAAA,CAAQ,CAAC,GAAA,KAAgB;AACjD,IAAA,SAAA,CAAU,GAAG,CAAA,GAAI,KAAA,CAAM,IAAA,CAAK,YAAA,CAAa,GAAG,CAAC,CAAA;AAC7C,IAAA,SAAA,CAAU,GAAG,EAAE,IAAA,CAAK,CAAC,GAAG,CAAA,KAAM,CAAA,CAAE,aAAA,CAAc,CAAC,CAAC,CAAA;AAAA,GACjD,CAAA;AACD,EAAA,OAAO,SAAA;AACT;AAEO,MAAM,eAAA,GAAkB,CAAC,KAAA,KAAsC;AACpE,EAAA,IAAI,QAAA,GAAW,MAAA;AACf,EAAA,IAAI,KAAA,IAAS,KAAA,CAAM,OAAA,CAAQ,GAAG,MAAM,EAAA,EAAI;AACtC,IAAA,QAAA,GAAW,KAAA,CAAM,KAAA,CAAM,GAAG,CAAA,CAAE,CAAC,CAAA;AAAA;AAG/B,EAAA,OAAO,QAAA;AACT;AAEO,MAAM,kBAAA,GAAqB,CAAC,KAAA,KAA+D;AAEhG,EAAA,MAAM,KAAA,GAAQ,uBAAA;AACd,EAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,KAAA,CAAM,KAAK,CAAA;AAE/B,EAAA,IAAI,KAAA,EAAO;AACT,IAAA,MAAM,WAAA,GAAc,MAAM,CAAC,CAAA;AAC3B,IAAA,MAAM,SAAA,GAAY,MAAM,CAAC,CAAA;AACzB,IAAA,OAAO,EAAE,aAA0B,SAAA,EAAqB;AAAA;AAG1D,EAAA,OAAO,EAAE,aAAa,KAAA,EAAM;AAC9B;AAGO,SAAS,SAAA,CAAU,MAAa,SAAA,EAAyB;AAC9D,EAAA,OAAO,IAAA,CAAK,IAAA;AAAA,IACV,CAAA,GAAA,KAAO,GAAA,CAAI,QAAA,KAAa,SAAA,CAAU,QAAA,IAAY,GAAA,CAAI,GAAA,KAAQ,SAAA,CAAU,GAAA,IAAO,GAAA,CAAI,KAAA,KAAU,SAAA,CAAU;AAAA,GACrG;AACF;AAGO,MAAM,YAAA,GAAe,CAAC,IAAA,KAAwB;AACnD,EAAA,IAAI,IAAA,CAAK,WAAW,CAAA,EAAG;AACrB,IAAA,OAAO,IAAA;AAAA;AAGT,EAAA,MAAM,aAAA,GAAgB,IAAA,CAAK,GAAA,CAAI,CAAA,GAAA,KAAO,CAAA,EAAG,GAAA,CAAI,QAAQ,CAAA,CAAA,EAAI,GAAA,CAAI,GAAG,CAAA,CAAA,EAAI,GAAA,CAAI,KAAK,CAAA,CAAE,CAAA;AAC/E,EAAA,OAAO,CAAA,CAAA,EAAI,aAAA,CAAc,IAAA,CAAK,MAAM,CAAC,CAAA,CAAA,CAAA;AACvC;AAEO,MAAM,gBAAA,GAAmB,CAAC,OAAA,KAAgC;AAC/D,EAAA,MAAM,IAAA,uBAAW,GAAA,EAAY;AAC7B,EAAA,MAAM,eAAe,CAAC,IAAA,EAAM,WAAW,SAAA,EAAW,UAAA,EAAY,YAAY,SAAS,CAAA;AACnF,EAAA,OAAA,CAAQ,QAAQ,CAAA,MAAA,KAAU;AACxB,IAAA,MAAA,CAAO,IAAA,CAAK,MAAM,CAAA,CAAE,OAAA,CAAQ,CAAA,GAAA,KAAO;AACjC,MAAA,IAAI,YAAA,CAAa,OAAA,CAAQ,GAAG,CAAA,KAAM,EAAA,EAAI;AACpC,QAAA,IAAA,CAAK,IAAI,GAAG,CAAA;AAAA;AACd,KACD,CAAA;AAAA,GACF,CAAA;AACD,EAAA,OAAO,KAAA,CAAM,KAAK,IAAI,CAAA;AACxB;AAEO,MAAM,gBAAA,GAAmB,CAAC,KAAA,KAA0B;AACzD,EAAA,MAAM,OAAO,KAAA,CAAM,KAAA,EAAO,SAAA,kBAAW,IAAI,MAAM,CAAA;AAC/C,EAAA,MAAM,aAAA,GAAgB,SAAA,CAAU,IAAA,EAAM,CAAC,CAAA;AACvC,EAAA,OAAO,MAAA,CAAO,eAAe,SAAS,CAAA;AACxC;AAEO,MAAM,cAAA,GAAiB,CAAC,GAAA,KAAwB;AACrD,EAAA,MAAM,OAAO,KAAA,CAAM,GAAA,EAAK,YAAA,kBAAc,IAAI,MAAM,CAAA;AAChD,EAAA,MAAM,WAAA,GAAc,OAAA,CAAQ,IAAA,EAAM,CAAC,CAAA;AACnC,EAAA,OAAO,MAAA,CAAO,aAAa,YAAY,CAAA;AACzC;AAEO,MAAM,gBAAA,GAAmB,CAAC,WAAA,EAAqB,SAAA,EAAiB,OAAA,KAA4B;AACjG,EAAA,MAAM,SAAmB,EAAC;AAC1B,EAAA,MAAM,OAAA,GAAU,OAAO,SAAS,CAAA;AAEhC,EAAA,OAAO,OAAA,CAAQ,eAAe,OAAO,CAAA,IAAK,QAAQ,cAAA,CAAe,MAAA,EAAQ,CAAA,EAAG;AAC1E,IAAA,IAAI,gBAAgB,SAAA,EAAW;AAC7B,MAAA,MAAA,CAAO,IAAA,CAAK,OAAA,CAAQ,MAAA,CAAO,SAAS,CAAC,CAAA;AACrC,MAAA,OAAA,CAAQ,GAAA,CAAI,GAAG,QAAQ,CAAA;AAAA,KACzB,MAAO;AACL,MAAA,MAAA,CAAO,IAAA,CAAK,OAAA,CAAQ,MAAA,CAAO,YAAY,CAAC,CAAA;AACxC,MAAA,OAAA,CAAQ,GAAA,CAAI,GAAG,MAAM,CAAA;AAAA;AACvB;AAGF,EAAA,OAAO,MAAA;AACT;AAEO,MAAM,cAAA,GAAiB,CAAC,MAAA,EAAgB,QAAA,KAA8B;AAC3E,EAAA,OAAO,IAAI,IAAA,CAAK,YAAA,CAAa,OAAA,EAAS;AAAA,IACpC,KAAA,EAAO,UAAA;AAAA,IACP,UAAsB,KAAA;AAAA,IACtB,QAAA,EAAU;AAAA,GACX,CAAA,CAAE,MAAA,CAAO,MAAM,CAAA;AAClB;AAkBO,MAAM,wBAAA,GAA2B,CACtC,YAAA,EACA,YAAA,KACoB;AACpB,EAAA,MAAM,YAAA,GAAe,MAAA,EAAO,CAAE,KAAA,EAAM,GAAI,CAAA;AACxC,EAAA,MAAM,WAAA,GAAc,MAAA,EAAO,CAAE,IAAA,EAAK;AAClC,EAAA,MAAM,oBAAA,GAAuB,MAAA,EAAO,CAAE,IAAA,EAAK;AAC3C,EAAA,MAAM,kBAAA,GAAqB,MAAA,EAAO,CAAE,WAAA,EAAY;AAEhD,EAAA,IAAI,eAAA,GAAkB,CAAA;AACtB,EAAA,MAAM,kBAA4B,EAAC;AAEnC,EAAA,KAAA,IAAS,KAAA,GAAQ,CAAA,EAAG,KAAA,IAAS,YAAA,EAAc,KAAA,EAAA,EAAS;AAClD,IAAA,MAAM,QAAA,GAAW,CAAA,EAAG,WAAW,CAAA,CAAA,EAAI,KAAA,CAAM,UAAS,CAAE,QAAA,CAAS,CAAA,EAAG,GAAG,CAAC,CAAA,CAAA;AACpE,IAAA,MAAM,SAAA,GAAY,YAAA,CAAa,QAAQ,CAAA,IAAK,CAAA;AAE5C,IAAA,IAAI,QAAQ,YAAA,EAAc;AACxB,MAAA,eAAA,IAAmB,SAAA;AACnB,MAAA,eAAA,CAAgB,KAAK,SAAS,CAAA;AAAA,KAChC,MAAA,IAAW,UAAU,YAAA,EAAc;AACjC,MAAA,MAAM,yBAAA,GAA6B,YAAY,oBAAA,GAAwB,kBAAA;AACvE,MAAA,eAAA,IAAmB,SAAA;AACnB,MAAA,eAAA,CAAgB,KAAK,yBAAyB,CAAA;AAAA;AAChD;AAGF,EAAA,MAAM,eAAA,GAAkB,EAAA,GAAK,YAAA,IAAgB,CAAA,GAAI,oBAAA,GAAuB,kBAAA,CAAA;AACxE,EAAA,MAAM,sBAAA,GACJ,eAAA,CAAgB,MAAA,GAAS,CAAA,GAAI,gBAAgB,MAAA,CAAO,CAAC,GAAA,EAAK,IAAA,KAAS,GAAA,GAAM,IAAA,EAAM,CAAC,CAAA,GAAI,gBAAgB,MAAA,GAAS,CAAA;AAE/G,EAAA,MAAM,cAAA,GAAiB,gBAAgB,MAAA,GAAS,CAAA,GAAI,gBAAgB,eAAA,CAAgB,MAAA,GAAS,CAAC,CAAA,IAAK,CAAA,GAAI,CAAA;AAEvG,EAAA,MAAM,uBAAA,GAA0B,kBAAkB,sBAAA,GAAyB,eAAA;AAE3E,EAAA,MAAM,wBAAA,GAA2B,YAAA,GAAe,CAAA,GAAK,eAAA,GAAkB,eAAgB,GAAA,GAAM,CAAA;AAC7F,EAAA,MAAM,0BAAA,GAAA,CAA+B,YAAA,GAAe,CAAA,GAAI,oBAAA,GAAuB,sBAAsB,EAAA,GAAM,GAAA;AAE3G,EAAA,IAAI,kBAAA,GAAyD,SAAA;AAC7D,EAAA,IAAI,wBAAA,GAA2B,6BAA6B,EAAA,EAAI;AAC9D,IAAA,kBAAA,GAAqB,UAAA;AAAA,GACvB,MAAA,IAAW,wBAAA,GAA2B,0BAAA,GAA6B,EAAA,EAAI;AACrE,IAAA,kBAAA,GAAqB,SAAA;AAAA;AAGvB,EAAA,MAAM,qBAAA,GAAwB,eAAA,GAAkB,CAAA,GAAA,CAAK,YAAA,GAAe,mBAAmB,eAAA,GAAkB,CAAA;AAEzG,EAAA,MAAM,gBAAA,GACJ,eAAA,CAAgB,MAAA,GAAS,CAAA,GACrB,IAAA,CAAK,IAAA;AAAA,IACH,eAAA,CAAgB,MAAA,CAAO,CAAC,GAAA,EAAK,SAAS,GAAA,GAAM,IAAA,CAAK,GAAA,CAAI,IAAA,GAAO,wBAAwB,CAAC,CAAA,EAAG,CAAC,CAAA,IACtF,gBAAgB,MAAA,GAAS,CAAA;AAAA,GAC9B,GACA,CAAA;AAEN,EAAA,MAAM,mBACJ,eAAA,CAAgB,MAAA,IAAU,KACpB,eAAA,CAAgB,eAAA,CAAgB,SAAS,CAAC,CAAA,GAAI,gBAAgB,eAAA,CAAgB,MAAA,GAAS,CAAC,CAAA,IACxF,eAAA,CAAgB,gBAAgB,MAAA,GAAS,CAAC,IAC5C,GAAA,GACA,CAAA;AAEN,EAAA,MAAM,eAAA,GAAkB;AAAA,IACtB,GAAA,EAAK,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,uBAAA,GAA0B,mBAAmB,CAAA,GAAI,IAAA,CAAK,IAAA,CAAK,eAAe,CAAC,CAAA;AAAA,IAC5F,MAAM,uBAAA,GAA0B,gBAAA,GAAmB,CAAA,GAAI,IAAA,CAAK,KAAK,eAAe;AAAA,GAClF;AAEA,EAAA,OAAO;AAAA,IACL,eAAA;AAAA,IACA,cAAA;AAAA,IACA,uBAAA;AAAA,IACA,kBAAA;AAAA,IACA,wBAAA;AAAA,IACA,qBAAA;AAAA,IACA,eAAA;AAAA,IACA,sBAAA;AAAA,IACA,gBAAA;AAAA,IACA;AAAA,GACF;AACF;;;;"}
@@ -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
- filtersSetter({ ...filters, [key]: newValue });
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}&nbsp;&nbsp;</>}\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}&nbsp;&nbsp;</>}\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("monthly");
85
- const [aggregatedBy, setAggregatedBy] = useState(defaultGroupBy);
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-20250929154750-e4ed5e3",
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",