@red-hat-developer-hub/plugin-cost-management 2.0.3-rc.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -0
- package/README.md +152 -0
- package/app-config.dynamic.yaml +28 -0
- package/dist/Router.esm.js +21 -0
- package/dist/Router.esm.js.map +1 -0
- package/dist/apis.esm.js +14 -0
- package/dist/apis.esm.js.map +1 -0
- package/dist/components/BasePage.esm.js +29 -0
- package/dist/components/BasePage.esm.js.map +1 -0
- package/dist/components/InfoCardTitle.esm.js +9 -0
- package/dist/components/InfoCardTitle.esm.js.map +1 -0
- package/dist/components/PageLayout.esm.js +56 -0
- package/dist/components/PageLayout.esm.js.map +1 -0
- package/dist/components/filtersStyles.esm.js +32 -0
- package/dist/components/filtersStyles.esm.js.map +1 -0
- package/dist/components/icon/AnalyticsIcon.esm.js +11 -0
- package/dist/components/icon/AnalyticsIcon.esm.js.map +1 -0
- package/dist/components/icon/AnalyticsIconFilled.esm.js +9 -0
- package/dist/components/icon/AnalyticsIconFilled.esm.js.map +1 -0
- package/dist/components/icon/AnalyticsIconOutlined.esm.js +9 -0
- package/dist/components/icon/AnalyticsIconOutlined.esm.js.map +1 -0
- package/dist/components/icon/CostManagementIcon.esm.js +11 -0
- package/dist/components/icon/CostManagementIcon.esm.js.map +1 -0
- package/dist/components/icon/CostManagementIconFilled.esm.js +9 -0
- package/dist/components/icon/CostManagementIconFilled.esm.js.map +1 -0
- package/dist/components/icon/CostManagementIconOutlined.esm.js +9 -0
- package/dist/components/icon/CostManagementIconOutlined.esm.js.map +1 -0
- package/dist/constants/currencies.esm.js +36 -0
- package/dist/constants/currencies.esm.js.map +1 -0
- package/dist/hooks/usePatternFlyTheme.esm.js +22 -0
- package/dist/hooks/usePatternFlyTheme.esm.js.map +1 -0
- package/dist/hooks/useThemeBackgroundColor.esm.js +13 -0
- package/dist/hooks/useThemeBackgroundColor.esm.js.map +1 -0
- package/dist/index.d.ts +71 -0
- package/dist/index.esm.js +9 -0
- package/dist/index.esm.js.map +1 -0
- package/dist/pages/openshift/OpenShiftPage.esm.js +727 -0
- package/dist/pages/openshift/OpenShiftPage.esm.js.map +1 -0
- package/dist/pages/openshift/components/AutocompleteComponent.esm.js +65 -0
- package/dist/pages/openshift/components/AutocompleteComponent.esm.js.map +1 -0
- package/dist/pages/openshift/components/DownloadIconButton.esm.js +49 -0
- package/dist/pages/openshift/components/DownloadIconButton.esm.js.map +1 -0
- package/dist/pages/openshift/components/Filters.esm.js +360 -0
- package/dist/pages/openshift/components/Filters.esm.js.map +1 -0
- package/dist/pages/openshift/components/PageHeader.esm.js +31 -0
- package/dist/pages/openshift/components/PageHeader.esm.js.map +1 -0
- package/dist/pages/openshift/components/SelectComponent.esm.js +68 -0
- package/dist/pages/openshift/components/SelectComponent.esm.js.map +1 -0
- package/dist/pages/openshift/components/TableToolbar.esm.js +249 -0
- package/dist/pages/openshift/components/TableToolbar.esm.js.map +1 -0
- package/dist/pages/optimizations/OptimizationsPage.esm.js +205 -0
- package/dist/pages/optimizations/OptimizationsPage.esm.js.map +1 -0
- package/dist/pages/optimizations/components/ComboBox.esm.js +84 -0
- package/dist/pages/optimizations/components/ComboBox.esm.js.map +1 -0
- package/dist/pages/optimizations/components/Filters.esm.js +59 -0
- package/dist/pages/optimizations/components/Filters.esm.js.map +1 -0
- package/dist/pages/optimizations/components/TableToolbar.esm.js +40 -0
- package/dist/pages/optimizations/components/TableToolbar.esm.js.map +1 -0
- package/dist/pages/optimizations-breakdown/OptimizationsBreakdownPage.esm.js +211 -0
- package/dist/pages/optimizations-breakdown/OptimizationsBreakdownPage.esm.js.map +1 -0
- package/dist/pages/optimizations-breakdown/components/optimization-engine-tab/OptimizationEngineTab.esm.js +132 -0
- package/dist/pages/optimizations-breakdown/components/optimization-engine-tab/OptimizationEngineTab.esm.js.map +1 -0
- package/dist/pages/optimizations-breakdown/components/optimization-engine-tab/components/CodeInfoCard.esm.js +37 -0
- package/dist/pages/optimizations-breakdown/components/optimization-engine-tab/components/CodeInfoCard.esm.js.map +1 -0
- package/dist/pages/optimizations-breakdown/components/optimization-engine-tab/components/ContainerInfoCard.esm.js +50 -0
- package/dist/pages/optimizations-breakdown/components/optimization-engine-tab/components/ContainerInfoCard.esm.js.map +1 -0
- package/dist/pages/optimizations-breakdown/components/optimization-engine-tab/components/chart-info-card/ChartInfoCard.esm.js +26 -0
- package/dist/pages/optimizations-breakdown/components/optimization-engine-tab/components/chart-info-card/ChartInfoCard.esm.js.map +1 -0
- package/dist/pages/optimizations-breakdown/components/optimization-engine-tab/components/chart-info-card/components/IntlBreakdownChart.esm.js +51 -0
- package/dist/pages/optimizations-breakdown/components/optimization-engine-tab/components/chart-info-card/components/IntlBreakdownChart.esm.js.map +1 -0
- package/dist/pages/optimizations-breakdown/components/optimization-engine-tab/components/chart-info-card/components/intl-breakdown-chart/components/optimizations-breakdown-chart/components/optimizations-breakdown-chart/OptimizationsBreakdownChart.esm.js +388 -0
- package/dist/pages/optimizations-breakdown/components/optimization-engine-tab/components/chart-info-card/components/intl-breakdown-chart/components/optimizations-breakdown-chart/components/optimizations-breakdown-chart/OptimizationsBreakdownChart.esm.js.map +1 -0
- package/dist/pages/optimizations-breakdown/components/optimization-engine-tab/components/chart-info-card/components/intl-breakdown-chart/components/optimizations-breakdown-chart/components/optimizations-breakdown-chart/i18n/data.json.esm.js +512 -0
- package/dist/pages/optimizations-breakdown/components/optimization-engine-tab/components/chart-info-card/components/intl-breakdown-chart/components/optimizations-breakdown-chart/components/optimizations-breakdown-chart/i18n/data.json.esm.js.map +1 -0
- package/dist/pages/optimizations-breakdown/components/optimization-engine-tab/components/chart-info-card/components/intl-breakdown-chart/components/optimizations-breakdown-chart/components/optimizations-breakdown-chart/i18n/intl.esm.js +18 -0
- package/dist/pages/optimizations-breakdown/components/optimization-engine-tab/components/chart-info-card/components/intl-breakdown-chart/components/optimizations-breakdown-chart/components/optimizations-breakdown-chart/i18n/intl.esm.js.map +1 -0
- package/dist/pages/optimizations-breakdown/components/optimization-engine-tab/components/chart-info-card/components/intl-breakdown-chart/components/optimizations-breakdown-chart/components/optimizations-breakdown-chart/i18n/messages.esm.js +72 -0
- package/dist/pages/optimizations-breakdown/components/optimization-engine-tab/components/chart-info-card/components/intl-breakdown-chart/components/optimizations-breakdown-chart/components/optimizations-breakdown-chart/i18n/messages.esm.js.map +1 -0
- package/dist/pages/optimizations-breakdown/components/optimization-engine-tab/components/chart-info-card/components/intl-breakdown-chart/components/optimizations-breakdown-chart/components/optimizations-breakdown-chart/utils/chart-data-format.esm.js +96 -0
- package/dist/pages/optimizations-breakdown/components/optimization-engine-tab/components/chart-info-card/components/intl-breakdown-chart/components/optimizations-breakdown-chart/components/optimizations-breakdown-chart/utils/chart-data-format.esm.js.map +1 -0
- package/dist/pages/optimizations-breakdown/components/optimization-engine-tab/components/chart-info-card/components/intl-breakdown-chart/components/optimizations-breakdown-chart/components/optimizations-breakdown-chart/utils/chart-datum.esm.js +74 -0
- package/dist/pages/optimizations-breakdown/components/optimization-engine-tab/components/chart-info-card/components/intl-breakdown-chart/components/optimizations-breakdown-chart/components/optimizations-breakdown-chart/utils/chart-datum.esm.js.map +1 -0
- package/dist/pages/optimizations-breakdown/components/optimization-engine-tab/components/chart-info-card/components/intl-breakdown-chart/components/optimizations-breakdown-chart/components/optimizations-breakdown-chart/utils/chart-utils.esm.js +109 -0
- package/dist/pages/optimizations-breakdown/components/optimization-engine-tab/components/chart-info-card/components/intl-breakdown-chart/components/optimizations-breakdown-chart/components/optimizations-breakdown-chart/utils/chart-utils.esm.js.map +1 -0
- package/dist/pages/optimizations-breakdown/components/optimization-engine-tab/components/chart-info-card/components/intl-breakdown-chart/components/optimizations-breakdown-chart/components/optimizations-breakdown-chart/utils/format.esm.js +25 -0
- package/dist/pages/optimizations-breakdown/components/optimization-engine-tab/components/chart-info-card/components/intl-breakdown-chart/components/optimizations-breakdown-chart/components/optimizations-breakdown-chart/utils/format.esm.js.map +1 -0
- package/dist/pages/optimizations-breakdown/models/ChartEnums.esm.js +23 -0
- package/dist/pages/optimizations-breakdown/models/ChartEnums.esm.js.map +1 -0
- package/dist/pages/optimizations-breakdown/models/YamlCodeData.esm.js +129 -0
- package/dist/pages/optimizations-breakdown/models/YamlCodeData.esm.js.map +1 -0
- package/dist/plugin.esm.js +73 -0
- package/dist/plugin.esm.js.map +1 -0
- package/dist/routes.esm.js +16 -0
- package/dist/routes.esm.js.map +1 -0
- package/dist/utils/dates.esm.js +37 -0
- package/dist/utils/dates.esm.js.map +1 -0
- package/package.json +110 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OpenShiftPage.esm.js","sources":["../../../src/pages/openshift/OpenShiftPage.tsx"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React, { useMemo, useState, useCallback, useRef } from 'react';\nimport type { ExportFormat } from '@red-hat-developer-hub/plugin-cost-management-common/clients';\nimport {\n Table,\n TableColumn,\n InfoCard,\n ResponseErrorPanel,\n} from '@backstage/core-components';\nimport Typography from '@material-ui/core/Typography';\nimport { BasePage } from '../../components/BasePage';\nimport { PageLayout } from '../../components/PageLayout';\nimport { Filters } from './components/Filters';\nimport { Divider, useTheme } from '@material-ui/core';\nimport { PageHeader } from './components/PageHeader';\nimport { TableToolbar } from './components/TableToolbar';\nimport { useApi } from '@backstage/core-plugin-api';\nimport { costManagementSlimApiRef } from '../../apis';\nimport useAsync from 'react-use/lib/useAsync';\nimport { CURRENCY_SYMBOLS } from '../../constants/currencies';\nimport { DownloadIconButton } from './components/DownloadIconButton';\n\nconst formatCurrency = (value: number, currencyCode: string): string => {\n const symbol = CURRENCY_SYMBOLS[currencyCode] || currencyCode;\n return `${symbol}${value.toLocaleString('en-US', {\n minimumFractionDigits: 2,\n maximumFractionDigits: 2,\n })}`;\n};\n\ninterface ProjectCost {\n id: string;\n projectName: string;\n clusterId?: string;\n cost: number;\n costPercentage: number;\n monthOverMonthChange: number;\n monthOverMonthValue: number;\n includesOverhead: boolean;\n previousPeriodCost: number;\n infrastructureCost: number;\n infrastructureCostPercentage: number;\n supplementaryCost: number;\n supplementaryCostPercentage: number;\n}\n\n/**\n * Generates date range text based on time range selection\n * @param timeRange - 'month-to-date' or 'previous-month'\n * @returns Formatted string like \"December 1-3\" or \"November 1-30\"\n */\nfunction getDateRangeText(timeRange: string): string {\n const now = new Date();\n const currentMonth = now.getMonth();\n const currentYear = now.getFullYear();\n const currentDay = now.getDate();\n\n if (timeRange === 'month-to-date') {\n // Current month: MONTH 1-<CURRENT_DAY>\n const monthName = now.toLocaleString('en-US', { month: 'long' });\n return `${monthName} 1-${currentDay}`;\n }\n // Previous month: PREVIOUS_MONTH 1-<LAST_DAY>\n const prevMonth = currentMonth === 0 ? 11 : currentMonth - 1;\n const prevYear = currentMonth === 0 ? currentYear - 1 : currentYear;\n const prevMonthDate = new Date(prevYear, prevMonth + 1, 0); // Last day of previous month\n const lastDay = prevMonthDate.getDate();\n const monthName = prevMonthDate.toLocaleString('en-US', { month: 'long' });\n return `${monthName} 1-${lastDay}`;\n}\n\n/**\n * Configuration for building query parameters\n */\ninterface QueryParamsConfig {\n groupBy: string;\n selectedTag: string;\n overheadDistribution: string;\n timeRange: string;\n currency: string;\n showPlatformSum: boolean;\n filterBy: string;\n filterValue: string;\n filterOperation: string;\n selectedTagKey: string;\n selectedTagValue: string;\n sortField: string | null;\n sortDirection: 'asc' | 'desc';\n}\n\n/**\n * Options for building query parameters\n */\ninterface BuildQueryParamsOptions {\n /** Pagination limit - omit for download (uses 0) */\n limit?: number;\n /** Pagination offset - omit for download */\n offset?: number;\n /** Specific item name to filter by (for row-level download) */\n specificItemName?: string;\n}\n\n/**\n * Builds query parameters for cost management API requests\n * Shared between data fetching and download functionality\n */\nfunction buildCostManagementQueryParams(\n config: QueryParamsConfig,\n options: BuildQueryParamsOptions = {},\n): Record<string, string | number> {\n const {\n groupBy,\n selectedTag,\n overheadDistribution,\n timeRange,\n currency,\n showPlatformSum,\n filterBy,\n filterValue,\n filterOperation,\n selectedTagKey,\n selectedTagValue,\n sortField,\n sortDirection,\n } = config;\n\n const { limit, offset, specificItemName } = options;\n\n // Build group by parameter\n const groupByParam =\n groupBy === 'tag' ? `group_by[tag:${selectedTag}]` : `group_by[${groupBy}]`;\n\n // Determine delta parameter\n const deltaParam =\n groupBy === 'project' && overheadDistribution === 'distribute'\n ? 'distributed_cost'\n : 'cost';\n\n const timeScopeValue = timeRange === 'month-to-date' ? -1 : -2;\n\n const queryParams: Record<string, string | number> = {\n currency,\n delta: deltaParam,\n 'filter[resolution]': 'monthly',\n 'filter[time_scope_units]': 'month',\n 'filter[time_scope_value]': timeScopeValue,\n };\n\n // Add pagination if provided\n if (limit !== undefined) {\n queryParams['filter[limit]'] = limit;\n }\n if (offset !== undefined) {\n queryParams['filter[offset]'] = offset;\n }\n\n // Add category parameter when showPlatformSum is enabled\n if (showPlatformSum) {\n queryParams.category = 'Platform';\n }\n\n queryParams[groupByParam] = '*';\n\n // Handle filtering\n if (specificItemName) {\n // Filter for specific item (row-level download)\n queryParams[`filter[${groupBy}]`] = specificItemName;\n } else if (filterBy === 'tag' && selectedTagKey && selectedTagValue) {\n // Tag filtering\n if (filterOperation === 'exact') {\n queryParams[`filter[exact:tag:${selectedTagKey}]`] = selectedTagValue;\n } else if (filterOperation === 'excludes') {\n queryParams[`exclude[tag:${selectedTagKey}]`] = selectedTagValue;\n } else {\n queryParams[`filter[tag:${selectedTagKey}]`] = selectedTagValue;\n }\n } else if (filterValue) {\n // Regular filtering\n if (filterOperation === 'exact') {\n queryParams[`filter[exact:${filterBy}]`] = filterValue;\n } else if (filterOperation === 'excludes') {\n queryParams[`exclude[${filterBy}]`] = filterValue;\n } else {\n queryParams[`filter[${filterBy}]`] = filterValue;\n }\n }\n\n // Add sorting\n let apiSortField: string;\n if (sortField) {\n if (sortField === 'cost') {\n apiSortField = deltaParam;\n } else if (sortField === 'projectName') {\n apiSortField = groupBy;\n } else {\n apiSortField = deltaParam;\n }\n queryParams[`order_by[${apiSortField}]`] = sortDirection;\n } else {\n queryParams[`order_by[${deltaParam}]`] = 'desc';\n }\n\n return queryParams;\n}\n\n/** @public */\nexport function OpenShiftPage() {\n const api = useApi(costManagementSlimApiRef);\n const [groupBy, setGroupBy] = useState('project');\n const [overheadDistribution, setOverheadDistribution] =\n useState('distribute');\n const [timeRange, setTimeRange] = useState('month-to-date');\n const [currency, setCurrency] = useState('USD');\n const [filterBy, setFilterBy] = useState('project');\n const [filterOperation, setFilterOperation] = useState('includes');\n const [filterValue, setFilterValue] = useState('');\n const [showPlatformSum, setShowPlatformSum] = useState(false);\n const [selectedRows, setSelectedRows] = useState<Set<string>>(new Set());\n const [currentPage, setCurrentPage] = useState(0);\n const [pageSize, setPageSize] = useState(5);\n const [sortField, setSortField] = useState<string | null>(null);\n const [sortDirection, setSortDirection] = useState<'asc' | 'desc'>('desc');\n const [tags, setTags] = useState<string[]>([]);\n const [selectedTag, setSelectedTag] = useState<string>('');\n const [selectedTagKey, setSelectedTagKey] = useState<string>('');\n const [selectedTagValue, setSelectedTagValue] = useState<string>('');\n const [showMonthOverMonthChange, setShowMonthOverMonthChange] =\n useState(true);\n const [showInfrastructureCost, setShowInfrastructureCost] = useState(false);\n const [showSupplementaryCost, setShowSupplementaryCost] = useState(false);\n const [isDownloading, setIsDownloading] = useState(false);\n const theme = useTheme();\n const isDarkMode = (theme.palette as any).mode === 'dark';\n\n // Ref to store display data for use in download handlers\n const displayDataRef = useRef<typeof displayData | null>(null);\n\n // Fetch tags on first load\n useAsync(async () => {\n try {\n const timeScopeValue = timeRange === 'month-to-date' ? -1 : -2;\n const response = await api.getOpenShiftTags(timeScopeValue);\n const tagsData = await response.json();\n setTags(tagsData.data || []);\n } catch {\n // Silently fail if tags can't be loaded\n setTags([]);\n }\n }, [api, timeRange]);\n\n // Build config object for query params builder (memoized to prevent unnecessary re-renders)\n const queryParamsConfig: QueryParamsConfig = useMemo(\n () => ({\n groupBy,\n selectedTag,\n overheadDistribution,\n timeRange,\n currency,\n showPlatformSum,\n filterBy,\n filterValue,\n filterOperation,\n selectedTagKey,\n selectedTagValue,\n sortField,\n sortDirection,\n }),\n [\n groupBy,\n selectedTag,\n overheadDistribution,\n timeRange,\n currency,\n showPlatformSum,\n filterBy,\n filterValue,\n filterOperation,\n selectedTagKey,\n selectedTagValue,\n sortField,\n sortDirection,\n ],\n );\n\n const {\n value: costData,\n loading,\n error,\n } = useAsync(async () => {\n // Don't make API call if groupBy is 'tag' but no tag is selected\n if (groupBy === 'tag' && !selectedTag) {\n return null;\n }\n\n const offset = currentPage * pageSize;\n const queryParams = buildCostManagementQueryParams(queryParamsConfig, {\n limit: pageSize,\n offset,\n });\n\n const response = await api.getCostManagementReport({\n query: queryParams,\n });\n return response.json();\n }, [\n currency,\n overheadDistribution,\n timeRange,\n groupBy,\n filterBy,\n filterValue,\n filterOperation,\n showPlatformSum,\n api,\n currentPage,\n pageSize,\n sortField,\n sortDirection,\n selectedTag,\n selectedTagKey,\n selectedTagValue,\n ]);\n\n const displayData = useMemo(() => {\n // If costData is null, return empty structure to keep table visible during loading\n if (!costData) {\n const today = new Date();\n const month =\n timeRange === 'previous-month'\n ? new Date(\n today.getFullYear(),\n today.getMonth() - 1,\n 1,\n ).toLocaleString('en-US', { month: 'long' })\n : today.toLocaleString('en-US', { month: 'long' });\n const endDate =\n timeRange === 'previous-month'\n ? new Date(today.getFullYear(), today.getMonth(), 0)\n .getDate()\n .toString()\n : today.getDate().toString();\n\n return {\n totalCost: 0,\n month,\n endDate,\n currencyCode: currency,\n projects: [],\n };\n }\n\n const arrayKey = `${groupBy}s` as keyof (typeof costData.data)[0];\n const groupedArray = costData.data?.[0]?.[arrayKey] as\n | Array<{ [key: string]: unknown; values: unknown[] }>\n | undefined;\n\n const projects =\n groupedArray?.map((item, index) => {\n const value =\n (item.values?.[0] as {\n cost?: {\n distributed?: { value?: number };\n total?: { value?: number };\n network_unattributed_distributed?: { value?: number };\n worker_unallocated_distributed?: { value?: number };\n platform_distributed?: { value?: number };\n storage_unattributed_distributed?: { value?: number };\n };\n infrastructure?: {\n total?: { value?: number };\n };\n supplementary?: {\n total?: { value?: number };\n };\n delta_percent?: number;\n delta_value?: number;\n }) || {};\n\n // For clusters, prefer values[0].clusters[0] (human-readable) over item.cluster (UUID)\n let itemName: string;\n let clusterId: string | undefined;\n if (groupBy === 'cluster') {\n const valueItem = item.values?.[0] as\n | { clusters?: string[]; cluster?: string }\n | undefined;\n const clustersArray = valueItem?.clusters;\n itemName =\n clustersArray && clustersArray.length > 0\n ? clustersArray[0]\n : (item.cluster as string) || 'Unknown';\n // Store the cluster UUID for display\n clusterId = (item.cluster as string) || undefined;\n } else {\n const nameField = groupBy as keyof typeof item;\n itemName = (item[nameField] as string) || 'Unknown';\n }\n\n const costField =\n groupBy === 'project' && overheadDistribution === 'distribute'\n ? 'distributed'\n : 'total';\n const costValue =\n value?.cost?.[costField as keyof typeof value.cost]?.value || 0;\n\n const deltaPercent = value?.delta_percent || 0;\n const deltaValue = value?.delta_value || 0;\n\n const infrastructureValue = value?.infrastructure?.total?.value || 0;\n const supplementaryValue = value?.supplementary?.total?.value || 0;\n\n return {\n id: `${index}`,\n projectName: itemName,\n clusterId,\n cost: costValue,\n costPercentage: 0,\n monthOverMonthChange: deltaPercent,\n monthOverMonthValue: Math.abs(deltaValue),\n includesOverhead:\n value?.cost?.network_unattributed_distributed?.value !== 0 ||\n value?.cost?.worker_unallocated_distributed?.value !== 0 ||\n value?.cost?.platform_distributed?.value !== 0 ||\n value?.cost?.storage_unattributed_distributed?.value !== 0,\n previousPeriodCost: costValue + Math.abs(deltaValue),\n infrastructureCost: infrastructureValue,\n infrastructureCostPercentage: 0,\n supplementaryCost: supplementaryValue,\n supplementaryCostPercentage: 0,\n };\n }) || [];\n\n const totalCost = costData.meta?.total?.cost?.total?.value || 0;\n const totalInfrastructureCost =\n costData.meta?.total?.infrastructure?.total?.value || 0;\n const totalSupplementaryCost =\n costData.meta?.total?.supplementary?.total?.value || 0;\n\n const currencyCode = costData.meta?.currency || currency;\n\n const projectsWithPercentage = projects.map(p => ({\n ...p,\n costPercentage: totalCost > 0 ? (p.cost / totalCost) * 100 : 0,\n infrastructureCostPercentage:\n totalInfrastructureCost > 0\n ? (p.infrastructureCost / totalInfrastructureCost) * 100\n : 0,\n supplementaryCostPercentage:\n totalSupplementaryCost > 0\n ? (p.supplementaryCost / totalSupplementaryCost) * 100\n : 0,\n }));\n\n let month: string;\n let endDate: string;\n\n if (timeRange === 'previous-month') {\n const today = new Date();\n const previousMonth = new Date(\n today.getFullYear(),\n today.getMonth() - 1,\n 1,\n );\n month = previousMonth.toLocaleString('en-US', { month: 'long' });\n const lastDayOfPreviousMonth = new Date(\n today.getFullYear(),\n today.getMonth(),\n 0,\n ).getDate();\n endDate = lastDayOfPreviousMonth.toString();\n } else {\n const today = new Date();\n month = today.toLocaleString('en-US', { month: 'long' });\n endDate = today.getDate().toString();\n }\n\n return {\n totalCost,\n month,\n endDate,\n currencyCode,\n projects: projectsWithPercentage,\n };\n }, [costData, currency, groupBy, overheadDistribution, timeRange]);\n\n // Update ref when displayData changes\n displayDataRef.current = displayData;\n\n /**\n * Builds query parameters for download request\n * @param specificItemName - Optional: specific item name to filter by (for row-level download)\n */\n const buildDownloadQueryParams = useCallback(\n (specificItemName?: string): Record<string, string | number> => {\n return buildCostManagementQueryParams(queryParamsConfig, {\n specificItemName,\n });\n },\n [queryParamsConfig],\n );\n\n /**\n * Handles download for header buttons (all data based on current filters)\n */\n const handleHeaderDownload = useCallback(\n async (format: ExportFormat) => {\n if (isDownloading) return;\n\n setIsDownloading(true);\n try {\n const queryParams = buildDownloadQueryParams();\n await api.downloadCostManagementReport({\n query: queryParams,\n format,\n });\n } catch (err) {\n // eslint-disable-next-line no-console\n console.error(`Failed to download ${format}:`, err);\n } finally {\n setIsDownloading(false);\n }\n },\n [api, buildDownloadQueryParams, isDownloading],\n );\n\n /**\n * Handles download for row-level buttons (specific item)\n */\n const handleRowDownload = useCallback(\n async (itemName: string, format: ExportFormat) => {\n if (isDownloading) return;\n\n setIsDownloading(true);\n try {\n const queryParams = buildDownloadQueryParams(itemName);\n await api.downloadCostManagementReport({\n query: queryParams,\n format,\n });\n } catch (err) {\n // eslint-disable-next-line no-console\n console.error(`Failed to download ${format} for ${itemName}:`, err);\n } finally {\n setIsDownloading(false);\n }\n },\n [api, buildDownloadQueryParams, isDownloading],\n );\n\n const handleRowSelect = useCallback(\n (rowId: string, isSelected: boolean) => {\n const newSelectedRows = new Set(selectedRows);\n if (isSelected) {\n newSelectedRows.add(rowId);\n } else {\n newSelectedRows.delete(rowId);\n }\n setSelectedRows(newSelectedRows);\n },\n [selectedRows],\n );\n\n const handleSelectAll = useCallback(\n (isSelected: boolean) => {\n if (isSelected && displayData) {\n setSelectedRows(\n new Set(displayData.projects.map(project => project.id)),\n );\n } else {\n setSelectedRows(new Set());\n }\n },\n [displayData],\n );\n\n const handlePageChange = useCallback((page: number, newPageSize: number) => {\n setCurrentPage(page);\n setPageSize(newPageSize);\n }, []);\n\n const handleRowsPerPageChange = useCallback((newPageSize: number) => {\n setPageSize(newPageSize);\n setCurrentPage(0);\n }, []);\n\n const totalCount = costData?.meta?.count || 0;\n\n const isAllSelected =\n displayData !== null &&\n selectedRows.size === displayData.projects.length &&\n displayData.projects.length > 0;\n const isIndeterminate =\n displayData !== null &&\n selectedRows.size > 0 &&\n selectedRows.size < displayData.projects.length;\n\n const columns = useMemo<TableColumn<ProjectCost>[]>(() => {\n const getChangeColor = (change: number) => {\n if (change < 0) return '#d32f2f';\n if (isDarkMode) return '#4BB543';\n return '#2e7d32';\n };\n\n const cols: TableColumn<ProjectCost>[] = [\n {\n title: (\n <div style={{ marginLeft: 0, paddingLeft: 0 }}>\n <input\n type=\"checkbox\"\n checked={isAllSelected}\n ref={input => {\n if (input) input.indeterminate = isIndeterminate;\n }}\n onChange={e => {\n e.stopPropagation();\n handleSelectAll(e.target.checked);\n }}\n style={{\n width: '18px',\n height: '18px',\n cursor: 'pointer',\n margin: 0,\n padding: 0,\n }}\n />\n </div>\n ),\n field: 'checkbox',\n sorting: false,\n width: '40px',\n cellStyle: {\n paddingLeft: '4px',\n paddingRight: '4px',\n },\n headerStyle: {\n paddingLeft: '4px',\n paddingRight: '4px',\n },\n render: data => (\n <div style={{ paddingRight: '4px' }}>\n <input\n type=\"checkbox\"\n checked={selectedRows.has(data.id)}\n onChange={e => handleRowSelect(data.id, e.target.checked)}\n style={{\n width: '18px',\n height: '18px',\n cursor: 'pointer',\n margin: 0,\n padding: 0,\n }}\n />\n </div>\n ),\n },\n {\n title: (\n <Typography variant=\"body2\" style={{ fontWeight: 'bold' }}>\n {groupBy.charAt(0).toLocaleUpperCase('en-US') + groupBy.slice(1)}{' '}\n name\n </Typography>\n ),\n field: 'projectName',\n cellStyle: { minWidth: 350 },\n headerStyle: { minWidth: 350 },\n render: data => (\n <div>\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n gap: '8px',\n }}\n >\n <Typography variant=\"body2\">{data.projectName}</Typography>\n {groupBy === 'project' && data.includesOverhead && (\n <Typography\n variant=\"caption\"\n style={{\n padding: '2px 6px',\n backgroundColor: '#F5F5F5',\n border: '1px solid #D2D2D2',\n borderRadius: '16px',\n color: 'black',\n whiteSpace: 'nowrap',\n }}\n >\n Includes overhead\n </Typography>\n )}\n </div>\n {groupBy === 'cluster' && data.clusterId && (\n <Typography\n variant=\"caption\"\n style={{ color: '#666', display: 'block', marginTop: 10 }}\n >\n {data.clusterId}\n </Typography>\n )}\n </div>\n ),\n },\n ];\n\n if (showMonthOverMonthChange) {\n cols.push({\n title: 'Month over month change',\n field: 'monthOverMonthChange',\n sorting: false,\n render: data => (\n <div>\n <div\n style={{\n color: getChangeColor(data.monthOverMonthChange),\n }}\n >\n {Math.abs(data.monthOverMonthChange).toFixed(2)}%\n {data.monthOverMonthChange > 0 ? ' ▲' : ' ▼'}\n </div>\n <div style={{ fontSize: '0.75rem', color: '#666' }}>\n {formatCurrency(\n data.monthOverMonthValue,\n displayData?.currencyCode || '',\n )}{' '}\n for {getDateRangeText(timeRange)}\n </div>\n </div>\n ),\n });\n }\n\n cols.push({\n title: 'Cost',\n field: 'cost',\n render: data => (\n <div>\n <div>\n {formatCurrency(data.cost, displayData?.currencyCode || '')}\n </div>\n <div style={{ fontSize: '0.75rem', color: '#666' }}>\n {data.costPercentage.toFixed(2)}% of cost\n </div>\n </div>\n ),\n });\n\n if (showInfrastructureCost) {\n cols.push({\n title: 'Infrastructure cost',\n field: 'infrastructureCost',\n render: data => (\n <div>\n <div>\n {formatCurrency(\n data.infrastructureCost,\n displayData?.currencyCode || '',\n )}\n </div>\n <div style={{ fontSize: '0.75rem', color: '#666' }}>\n {data.infrastructureCostPercentage.toFixed(2)}% of cost\n </div>\n </div>\n ),\n });\n }\n\n if (showSupplementaryCost) {\n cols.push({\n title: 'Supplementary cost',\n field: 'supplementaryCost',\n render: data => (\n <div>\n <div>\n {formatCurrency(\n data.supplementaryCost,\n displayData?.currencyCode || '',\n )}\n </div>\n <div style={{ fontSize: '0.75rem', color: '#666' }}>\n {data.supplementaryCostPercentage.toFixed(2)}% of cost\n </div>\n </div>\n ),\n });\n }\n\n cols.push({\n title: 'Actions',\n field: 'actions',\n sorting: false,\n render: data => (\n <div style={{ display: 'flex', gap: '8px' }}>\n <DownloadIconButton\n label=\"CSV\"\n variant={isDarkMode ? 'white' : 'black'}\n onClick={() => handleRowDownload(data.projectName, 'csv')}\n disabled={isDownloading}\n />\n <DownloadIconButton\n label=\"JSON\"\n variant={isDarkMode ? 'white' : 'black'}\n onClick={() => handleRowDownload(data.projectName, 'json')}\n disabled={isDownloading}\n />\n </div>\n ),\n });\n\n return cols;\n }, [\n handleRowSelect,\n handleRowDownload,\n isAllSelected,\n isIndeterminate,\n isDownloading,\n selectedRows,\n handleSelectAll,\n displayData?.currencyCode,\n groupBy,\n showMonthOverMonthChange,\n showInfrastructureCost,\n showSupplementaryCost,\n timeRange,\n isDarkMode,\n ]);\n\n const handleOrderChange = useCallback(\n (orderBy: number, orderDirection: 'asc' | 'desc') => {\n // If orderBy is -1, it means \"no sorting\" - ignore it to prevent removing sorting\n if (orderBy === -1) {\n return;\n }\n\n const column = columns[orderBy];\n if (\n column?.field &&\n column.field !== 'actions' &&\n column.sorting !== false\n ) {\n const newField = column.field as string;\n setSortField(newField);\n setSortDirection(orderDirection);\n\n setCurrentPage(0);\n }\n },\n [columns],\n );\n\n if (error) {\n return <ResponseErrorPanel error={error} />;\n }\n\n return (\n <BasePage pageTitle=\"\" withContentPadding>\n <PageHeader\n totalCost={displayData.totalCost}\n month={displayData.month}\n endDate={displayData.endDate}\n currencyCode={displayData.currencyCode}\n customStyle={{ marginTop: '-24px' }}\n />\n\n <Divider\n style={{\n marginBottom: 24,\n marginLeft: '-24px',\n marginRight: '-24px',\n width: 'calc(100% + 48px)',\n }}\n />\n\n <PageLayout>\n <PageLayout.Filters>\n <Filters\n groupBy={groupBy}\n overheadDistribution={overheadDistribution}\n timeRange={timeRange}\n currency={currency}\n filterBy={filterBy}\n filterOperation={filterOperation}\n filterValue={filterValue}\n tags={tags}\n onGroupByChange={value => {\n setGroupBy(value);\n setCurrentPage(0);\n if (value !== 'tag') {\n setSelectedTag('');\n }\n // Reset showPlatformSum when groupBy changes away from 'project'\n if (value !== 'project') {\n setShowPlatformSum(false);\n }\n // Sync filterBy with groupBy and reset filter value\n setFilterBy(value);\n setFilterValue('');\n // Reset tag-related filter fields\n setSelectedTagKey('');\n setSelectedTagValue('');\n }}\n selectedTag={selectedTag}\n onSelectedTagChange={value => {\n setSelectedTag(value);\n setCurrentPage(0);\n }}\n onOverheadDistributionChange={value => {\n setOverheadDistribution(value);\n setCurrentPage(0);\n }}\n onTimeRangeChange={value => {\n setTimeRange(value);\n setCurrentPage(0);\n }}\n onCurrencyChange={value => {\n setCurrency(value);\n setCurrentPage(0);\n }}\n onFilterByChange={value => {\n setFilterBy(value);\n setCurrentPage(0);\n // Clear tag-related selections when filterBy changes away from 'tag'\n if (value !== 'tag') {\n setSelectedTagKey('');\n setSelectedTagValue('');\n }\n }}\n onFilterOperationChange={value => {\n setFilterOperation(value);\n setCurrentPage(0);\n }}\n onFilterValueChange={value => {\n setFilterValue(value);\n setCurrentPage(0);\n }}\n selectedTagKey={selectedTagKey}\n selectedTagValue={selectedTagValue}\n onSelectedTagKeyChange={value => {\n setSelectedTagKey(value);\n setSelectedTagValue('');\n setCurrentPage(0);\n }}\n onSelectedTagValueChange={value => {\n setSelectedTagValue(value);\n setCurrentPage(0);\n }}\n />\n </PageLayout.Filters>\n <PageLayout.Table>\n <div style={{ flex: 1 }}>\n <InfoCard>\n <Table<ProjectCost>\n data={displayData?.projects || []}\n isLoading={loading}\n components={{\n Toolbar: () => (\n <TableToolbar\n showPlatformSum={showPlatformSum}\n setShowPlatformSum={setShowPlatformSum}\n projectsCount={displayData?.projects?.length || 0}\n groupBy={groupBy}\n showMonthOverMonthChange={showMonthOverMonthChange}\n setShowMonthOverMonthChange={setShowMonthOverMonthChange}\n showInfrastructureCost={showInfrastructureCost}\n setShowInfrastructureCost={setShowInfrastructureCost}\n showSupplementaryCost={showSupplementaryCost}\n setShowSupplementaryCost={setShowSupplementaryCost}\n onDownloadCsv={() => handleHeaderDownload('csv')}\n onDownloadJson={() => handleHeaderDownload('json')}\n isDownloading={isDownloading}\n />\n ),\n }}\n columns={columns}\n options={{\n paging: true,\n pageSize: pageSize,\n pageSizeOptions: [5, 10, 25, 50],\n search: false,\n sorting: true,\n padding: 'dense',\n thirdSortClick: false,\n }}\n totalCount={totalCount}\n page={currentPage}\n onPageChange={handlePageChange}\n onRowsPerPageChange={handleRowsPerPageChange}\n onOrderChange={handleOrderChange}\n style={{ outline: 'none' }}\n localization={{\n pagination: {\n labelRowsPerPage: 'rows',\n },\n }}\n />\n </InfoCard>\n </div>\n </PageLayout.Table>\n </PageLayout>\n </BasePage>\n );\n}\nOpenShiftPage.displayName = 'OpenShiftPage';\n"],"names":["monthName","month","endDate"],"mappings":"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"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { makeStyles } from '@material-ui/core/styles';
|
|
3
|
+
import Box from '@material-ui/core/Box';
|
|
4
|
+
import TextField from '@material-ui/core/TextField';
|
|
5
|
+
import Typography from '@material-ui/core/Typography';
|
|
6
|
+
import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
|
|
7
|
+
import { Autocomplete } from '@material-ui/lab';
|
|
8
|
+
import { useThemeBackgroundColor } from '../../../hooks/useThemeBackgroundColor.esm.js';
|
|
9
|
+
|
|
10
|
+
const useAutocompleteStyles = makeStyles(
|
|
11
|
+
{
|
|
12
|
+
root: {},
|
|
13
|
+
label: {},
|
|
14
|
+
input: { backgroundColor: "transparent" },
|
|
15
|
+
fullWidth: { width: "100%" }
|
|
16
|
+
},
|
|
17
|
+
{ name: "AutocompleteComponent" }
|
|
18
|
+
);
|
|
19
|
+
function AutocompleteComponent(props) {
|
|
20
|
+
const classes = useAutocompleteStyles();
|
|
21
|
+
const { label, options, placeholder, className } = props;
|
|
22
|
+
const { backgroundColor } = useThemeBackgroundColor();
|
|
23
|
+
return /* @__PURE__ */ React.createElement(Box, { className: className ?? classes.root, pb: 1, pt: 1 }, /* @__PURE__ */ React.createElement(
|
|
24
|
+
Typography,
|
|
25
|
+
{
|
|
26
|
+
className: classes.label,
|
|
27
|
+
variant: "button",
|
|
28
|
+
component: "label",
|
|
29
|
+
style: { textTransform: "none" }
|
|
30
|
+
},
|
|
31
|
+
label
|
|
32
|
+
), /* @__PURE__ */ React.createElement(
|
|
33
|
+
Autocomplete,
|
|
34
|
+
{
|
|
35
|
+
options,
|
|
36
|
+
multiple: Boolean(props.multiple),
|
|
37
|
+
value: props.value ?? (Boolean(props.multiple) ? [] : null),
|
|
38
|
+
onChange: (event, value, reason, details) => {
|
|
39
|
+
if (props.onChange) {
|
|
40
|
+
props.onChange(event, value, reason, details);
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
onInputChange: (event, value, reason) => {
|
|
44
|
+
if (props.onInputChange) {
|
|
45
|
+
props.onInputChange(event, value, reason);
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
loading: props.loading ?? false,
|
|
49
|
+
popupIcon: /* @__PURE__ */ React.createElement(ExpandMoreIcon, { "data-testid": "expand-icon" }),
|
|
50
|
+
renderInput: (params) => /* @__PURE__ */ React.createElement(
|
|
51
|
+
TextField,
|
|
52
|
+
{
|
|
53
|
+
...params,
|
|
54
|
+
variant: "outlined",
|
|
55
|
+
placeholder,
|
|
56
|
+
style: { backgroundColor }
|
|
57
|
+
}
|
|
58
|
+
),
|
|
59
|
+
size: "medium"
|
|
60
|
+
}
|
|
61
|
+
));
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export { AutocompleteComponent };
|
|
65
|
+
//# sourceMappingURL=AutocompleteComponent.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AutocompleteComponent.esm.js","sources":["../../../../src/pages/openshift/components/AutocompleteComponent.tsx"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React from 'react';\nimport { makeStyles } from '@material-ui/core/styles';\nimport Box from '@material-ui/core/Box';\nimport TextField from '@material-ui/core/TextField';\nimport Typography from '@material-ui/core/Typography';\nimport ExpandMoreIcon from '@material-ui/icons/ExpandMore';\nimport {\n Autocomplete,\n AutocompleteChangeDetails,\n AutocompleteChangeReason,\n} from '@material-ui/lab';\nimport { useThemeBackgroundColor } from '../../../hooks/useThemeBackgroundColor';\n\nconst useAutocompleteStyles = makeStyles(\n {\n root: {},\n label: {},\n input: { backgroundColor: 'transparent' },\n fullWidth: { width: '100%' },\n },\n { name: 'AutocompleteComponent' },\n);\n\ntype BaseProps = {\n label: string;\n options: string[];\n placeholder?: string;\n className?: string;\n};\n\ntype SingleProps = BaseProps & {\n multiple?: false;\n value?: string;\n onChange?: (\n event: React.ChangeEvent<{}>,\n value: string | null,\n reason: AutocompleteChangeReason,\n details?: AutocompleteChangeDetails<string> | undefined,\n ) => void;\n onInputChange?: (\n event: React.ChangeEvent<{}>,\n value: string,\n reason: string,\n ) => void;\n loading?: boolean;\n};\n\ntype MultipleProps = BaseProps & {\n multiple: true;\n value?: string[];\n onChange?: (\n event: React.ChangeEvent<{}>,\n value: string[],\n reason: AutocompleteChangeReason,\n details?: AutocompleteChangeDetails<string> | undefined,\n ) => void;\n};\n\ntype AutocompleteComponentProps = SingleProps | MultipleProps;\n\n/** @public */\nexport function AutocompleteComponent(props: AutocompleteComponentProps) {\n const classes = useAutocompleteStyles();\n const { label, options, placeholder, className } = props;\n const { backgroundColor } = useThemeBackgroundColor();\n\n return (\n <Box className={className ?? classes.root} pb={1} pt={1}>\n <Typography\n className={classes.label}\n variant=\"button\"\n component=\"label\"\n style={{ textTransform: 'none' }}\n >\n {label}\n </Typography>\n <Autocomplete\n options={options}\n multiple={Boolean((props as MultipleProps).multiple)}\n value={\n (props as any).value ??\n (Boolean((props as MultipleProps).multiple) ? [] : null)\n }\n onChange={(event, value, reason, details) => {\n if (props.onChange) {\n // Cast is safe because the callback shape matches the multiple flag\n (props.onChange as any)(event, value, reason, details);\n }\n }}\n onInputChange={(event, value, reason) => {\n if ((props as SingleProps).onInputChange) {\n (props as SingleProps).onInputChange!(event, value, reason);\n }\n }}\n loading={(props as SingleProps).loading ?? false}\n popupIcon={<ExpandMoreIcon data-testid=\"expand-icon\" />}\n renderInput={params => (\n <TextField\n {...params}\n variant=\"outlined\"\n placeholder={placeholder}\n style={{ backgroundColor }}\n />\n )}\n size=\"medium\"\n />\n </Box>\n );\n}\n"],"names":[],"mappings":";;;;;;;;;AA6BA,MAAM,qBAAwB,GAAA,UAAA;AAAA,EAC5B;AAAA,IACE,MAAM,EAAC;AAAA,IACP,OAAO,EAAC;AAAA,IACR,KAAA,EAAO,EAAE,eAAA,EAAiB,aAAc,EAAA;AAAA,IACxC,SAAA,EAAW,EAAE,KAAA,EAAO,MAAO;AAAA,GAC7B;AAAA,EACA,EAAE,MAAM,uBAAwB;AAClC,CAAA;AAwCO,SAAS,sBAAsB,KAAmC,EAAA;AACvE,EAAA,MAAM,UAAU,qBAAsB,EAAA;AACtC,EAAA,MAAM,EAAE,KAAA,EAAO,OAAS,EAAA,WAAA,EAAa,WAAc,GAAA,KAAA;AACnD,EAAM,MAAA,EAAE,eAAgB,EAAA,GAAI,uBAAwB,EAAA;AAEpD,EACE,uBAAA,KAAA,CAAA,aAAA,CAAC,OAAI,SAAW,EAAA,SAAA,IAAa,QAAQ,IAAM,EAAA,EAAA,EAAI,CAAG,EAAA,EAAA,EAAI,CACpD,EAAA,kBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,UAAA;AAAA,IAAA;AAAA,MACC,WAAW,OAAQ,CAAA,KAAA;AAAA,MACnB,OAAQ,EAAA,QAAA;AAAA,MACR,SAAU,EAAA,OAAA;AAAA,MACV,KAAA,EAAO,EAAE,aAAA,EAAe,MAAO;AAAA,KAAA;AAAA,IAE9B;AAAA,GAEH,kBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,YAAA;AAAA,IAAA;AAAA,MACC,OAAA;AAAA,MACA,QAAA,EAAU,OAAS,CAAA,KAAA,CAAwB,QAAQ,CAAA;AAAA,MACnD,KAAA,EACG,MAAc,KACd,KAAA,OAAA,CAAS,MAAwB,QAAQ,CAAA,GAAI,EAAK,GAAA,IAAA,CAAA;AAAA,MAErD,QAAU,EAAA,CAAC,KAAO,EAAA,KAAA,EAAO,QAAQ,OAAY,KAAA;AAC3C,QAAA,IAAI,MAAM,QAAU,EAAA;AAElB,UAAC,KAAM,CAAA,QAAA,CAAiB,KAAO,EAAA,KAAA,EAAO,QAAQ,OAAO,CAAA;AAAA;AACvD,OACF;AAAA,MACA,aAAe,EAAA,CAAC,KAAO,EAAA,KAAA,EAAO,MAAW,KAAA;AACvC,QAAA,IAAK,MAAsB,aAAe,EAAA;AACxC,UAAC,KAAsB,CAAA,aAAA,CAAe,KAAO,EAAA,KAAA,EAAO,MAAM,CAAA;AAAA;AAC5D,OACF;AAAA,MACA,OAAA,EAAU,MAAsB,OAAW,IAAA,KAAA;AAAA,MAC3C,SAAW,kBAAA,KAAA,CAAA,aAAA,CAAC,cAAe,EAAA,EAAA,aAAA,EAAY,aAAc,EAAA,CAAA;AAAA,MACrD,aAAa,CACX,MAAA,qBAAA,KAAA,CAAA,aAAA;AAAA,QAAC,SAAA;AAAA,QAAA;AAAA,UACE,GAAG,MAAA;AAAA,UACJ,OAAQ,EAAA,UAAA;AAAA,UACR,WAAA;AAAA,UACA,KAAA,EAAO,EAAE,eAAgB;AAAA;AAAA,OAC3B;AAAA,MAEF,IAAK,EAAA;AAAA;AAAA,GAET,CAAA;AAEJ;;;;"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import Typography from '@material-ui/core/Typography';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
|
|
4
|
+
const getColor = (variant, disabled) => {
|
|
5
|
+
if (disabled) return "#999999";
|
|
6
|
+
if (variant === "gray") return "#C7C7C7";
|
|
7
|
+
if (variant === "black") return "#000000";
|
|
8
|
+
if (variant === "white") return "#FFFFFF";
|
|
9
|
+
return "#C7C7C7";
|
|
10
|
+
};
|
|
11
|
+
function DownloadIconButton(props) {
|
|
12
|
+
const { label, variant, onClick, disabled } = props;
|
|
13
|
+
const color = getColor(variant, disabled);
|
|
14
|
+
return /* @__PURE__ */ React.createElement(
|
|
15
|
+
"div",
|
|
16
|
+
{
|
|
17
|
+
role: "button",
|
|
18
|
+
tabIndex: disabled ? -1 : 0,
|
|
19
|
+
onClick: disabled ? void 0 : onClick,
|
|
20
|
+
onKeyDown: disabled ? void 0 : (e) => {
|
|
21
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
22
|
+
e.preventDefault();
|
|
23
|
+
onClick?.();
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
style: {
|
|
27
|
+
border: `2px solid ${color}`,
|
|
28
|
+
borderRadius: 2,
|
|
29
|
+
display: "flex",
|
|
30
|
+
alignItems: "center",
|
|
31
|
+
justifyContent: "center",
|
|
32
|
+
cursor: disabled ? "not-allowed" : "pointer",
|
|
33
|
+
paddingTop: 2,
|
|
34
|
+
opacity: disabled ? 0.6 : 1
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
/* @__PURE__ */ React.createElement(
|
|
38
|
+
Typography,
|
|
39
|
+
{
|
|
40
|
+
variant: "body2",
|
|
41
|
+
style: { color, fontSize: 9, fontWeight: "bold" }
|
|
42
|
+
},
|
|
43
|
+
label
|
|
44
|
+
)
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export { DownloadIconButton };
|
|
49
|
+
//# sourceMappingURL=DownloadIconButton.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DownloadIconButton.esm.js","sources":["../../../../src/pages/openshift/components/DownloadIconButton.tsx"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport Typography from '@material-ui/core/Typography';\nimport React from 'react';\n\ntype DownloadIconButtonProps = {\n label: string;\n variant: 'gray' | 'black' | 'white';\n onClick?: () => void;\n disabled?: boolean;\n};\n\nconst getColor = (variant: 'gray' | 'black' | 'white', disabled?: boolean) => {\n if (disabled) return '#999999';\n if (variant === 'gray') return '#C7C7C7';\n if (variant === 'black') return '#000000';\n if (variant === 'white') return '#FFFFFF';\n return '#C7C7C7';\n};\n\nexport function DownloadIconButton(props: Readonly<DownloadIconButtonProps>) {\n const { label, variant, onClick, disabled } = props;\n const color = getColor(variant, disabled);\n\n return (\n <div\n role=\"button\"\n tabIndex={disabled ? -1 : 0}\n onClick={disabled ? undefined : onClick}\n onKeyDown={\n disabled\n ? undefined\n : e => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n onClick?.();\n }\n }\n }\n style={{\n border: `2px solid ${color}`,\n borderRadius: 2,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n cursor: disabled ? 'not-allowed' : 'pointer',\n paddingTop: 2,\n opacity: disabled ? 0.6 : 1,\n }}\n >\n <Typography\n variant=\"body2\"\n style={{ color, fontSize: 9, fontWeight: 'bold' }}\n >\n {label}\n </Typography>\n </div>\n );\n}\n"],"names":[],"mappings":";;;AA0BA,MAAM,QAAA,GAAW,CAAC,OAAA,EAAqC,QAAuB,KAAA;AAC5E,EAAA,IAAI,UAAiB,OAAA,SAAA;AACrB,EAAI,IAAA,OAAA,KAAY,QAAe,OAAA,SAAA;AAC/B,EAAI,IAAA,OAAA,KAAY,SAAgB,OAAA,SAAA;AAChC,EAAI,IAAA,OAAA,KAAY,SAAgB,OAAA,SAAA;AAChC,EAAO,OAAA,SAAA;AACT,CAAA;AAEO,SAAS,mBAAmB,KAA0C,EAAA;AAC3E,EAAA,MAAM,EAAE,KAAA,EAAO,OAAS,EAAA,OAAA,EAAS,UAAa,GAAA,KAAA;AAC9C,EAAM,MAAA,KAAA,GAAQ,QAAS,CAAA,OAAA,EAAS,QAAQ,CAAA;AAExC,EACE,uBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,IAAK,EAAA,QAAA;AAAA,MACL,QAAA,EAAU,WAAW,EAAK,GAAA,CAAA;AAAA,MAC1B,OAAA,EAAS,WAAW,MAAY,GAAA,OAAA;AAAA,MAChC,SAAA,EACE,QACI,GAAA,MAAA,GACA,CAAK,CAAA,KAAA;AACH,QAAA,IAAI,CAAE,CAAA,GAAA,KAAQ,OAAW,IAAA,CAAA,CAAE,QAAQ,GAAK,EAAA;AACtC,UAAA,CAAA,CAAE,cAAe,EAAA;AACjB,UAAU,OAAA,IAAA;AAAA;AACZ,OACF;AAAA,MAEN,KAAO,EAAA;AAAA,QACL,MAAA,EAAQ,aAAa,KAAK,CAAA,CAAA;AAAA,QAC1B,YAAc,EAAA,CAAA;AAAA,QACd,OAAS,EAAA,MAAA;AAAA,QACT,UAAY,EAAA,QAAA;AAAA,QACZ,cAAgB,EAAA,QAAA;AAAA,QAChB,MAAA,EAAQ,WAAW,aAAgB,GAAA,SAAA;AAAA,QACnC,UAAY,EAAA,CAAA;AAAA,QACZ,OAAA,EAAS,WAAW,GAAM,GAAA;AAAA;AAC5B,KAAA;AAAA,oBAEA,KAAA,CAAA,aAAA;AAAA,MAAC,UAAA;AAAA,MAAA;AAAA,QACC,OAAQ,EAAA,OAAA;AAAA,QACR,OAAO,EAAE,KAAA,EAAO,QAAU,EAAA,CAAA,EAAG,YAAY,MAAO;AAAA,OAAA;AAAA,MAE/C;AAAA;AACH,GACF;AAEJ;;;;"}
|
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
import React, { useState, useMemo, useEffect, useCallback } from 'react';
|
|
2
|
+
import Box from '@material-ui/core/Box';
|
|
3
|
+
import Divider from '@material-ui/core/Divider';
|
|
4
|
+
import { makeStyles } from '@material-ui/core/styles';
|
|
5
|
+
import { useBaseFiltersStyles } from '../../../components/filtersStyles.esm.js';
|
|
6
|
+
import { SelectComponent } from './SelectComponent.esm.js';
|
|
7
|
+
import { AutocompleteComponent } from './AutocompleteComponent.esm.js';
|
|
8
|
+
import { useApi } from '@backstage/core-plugin-api';
|
|
9
|
+
import { costManagementSlimApiRef } from '../../../apis.esm.js';
|
|
10
|
+
import useAsync from 'react-use/lib/useAsync';
|
|
11
|
+
import debounce from 'lodash/debounce';
|
|
12
|
+
import { useThemeBackgroundColor } from '../../../hooks/useThemeBackgroundColor.esm.js';
|
|
13
|
+
|
|
14
|
+
const useFiltersStyles = makeStyles(
|
|
15
|
+
(theme) => ({
|
|
16
|
+
filters: {
|
|
17
|
+
"& > *": {
|
|
18
|
+
marginTop: theme.spacing(0)
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
filterSection: {
|
|
22
|
+
marginBottom: theme.spacing(0)
|
|
23
|
+
},
|
|
24
|
+
divider: {
|
|
25
|
+
margin: theme.spacing(2, 0)
|
|
26
|
+
}
|
|
27
|
+
}),
|
|
28
|
+
{ name: "OpenShiftFilters" }
|
|
29
|
+
);
|
|
30
|
+
function Filters(props) {
|
|
31
|
+
const {
|
|
32
|
+
groupBy,
|
|
33
|
+
overheadDistribution,
|
|
34
|
+
timeRange,
|
|
35
|
+
currency,
|
|
36
|
+
filterBy,
|
|
37
|
+
filterOperation,
|
|
38
|
+
filterValue,
|
|
39
|
+
tags = [],
|
|
40
|
+
selectedTag = "",
|
|
41
|
+
selectedTagKey = "",
|
|
42
|
+
selectedTagValue = "",
|
|
43
|
+
onGroupByChange,
|
|
44
|
+
onOverheadDistributionChange,
|
|
45
|
+
onTimeRangeChange,
|
|
46
|
+
onCurrencyChange,
|
|
47
|
+
onFilterByChange,
|
|
48
|
+
onFilterOperationChange,
|
|
49
|
+
onFilterValueChange,
|
|
50
|
+
onSelectedTagChange,
|
|
51
|
+
onSelectedTagKeyChange,
|
|
52
|
+
onSelectedTagValueChange
|
|
53
|
+
} = props;
|
|
54
|
+
const baseClasses = useBaseFiltersStyles();
|
|
55
|
+
const classes = useFiltersStyles();
|
|
56
|
+
const api = useApi(costManagementSlimApiRef);
|
|
57
|
+
const { filterTableBackgroundColor } = useThemeBackgroundColor();
|
|
58
|
+
const [searchInput, setSearchInput] = useState("");
|
|
59
|
+
const [debouncedSearch, setDebouncedSearch] = useState("");
|
|
60
|
+
const debouncedSetSearch = useMemo(
|
|
61
|
+
() => debounce((value) => {
|
|
62
|
+
setDebouncedSearch(value);
|
|
63
|
+
}, 500),
|
|
64
|
+
[]
|
|
65
|
+
);
|
|
66
|
+
useEffect(() => {
|
|
67
|
+
debouncedSetSearch(searchInput);
|
|
68
|
+
return () => {
|
|
69
|
+
debouncedSetSearch.cancel();
|
|
70
|
+
};
|
|
71
|
+
}, [searchInput, debouncedSetSearch]);
|
|
72
|
+
useEffect(() => {
|
|
73
|
+
setSearchInput("");
|
|
74
|
+
setDebouncedSearch("");
|
|
75
|
+
}, [filterBy]);
|
|
76
|
+
const { value: resourceOptions, loading: isLoadingOptions } = useAsync(async () => {
|
|
77
|
+
if (filterBy === "tag") {
|
|
78
|
+
if (!debouncedSearch.trim()) {
|
|
79
|
+
return tags;
|
|
80
|
+
}
|
|
81
|
+
const searchLower = debouncedSearch.toLocaleLowerCase("en-US");
|
|
82
|
+
return tags.filter(
|
|
83
|
+
(tag) => tag.toLocaleLowerCase("en-US").includes(searchLower)
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
if (!debouncedSearch.trim()) {
|
|
87
|
+
return [];
|
|
88
|
+
}
|
|
89
|
+
try {
|
|
90
|
+
let response;
|
|
91
|
+
switch (filterBy) {
|
|
92
|
+
case "project":
|
|
93
|
+
response = await api.searchOpenShiftProjects(debouncedSearch);
|
|
94
|
+
break;
|
|
95
|
+
case "cluster":
|
|
96
|
+
response = await api.searchOpenShiftClusters(debouncedSearch);
|
|
97
|
+
break;
|
|
98
|
+
case "node":
|
|
99
|
+
response = await api.searchOpenShiftNodes(debouncedSearch);
|
|
100
|
+
break;
|
|
101
|
+
default:
|
|
102
|
+
return [];
|
|
103
|
+
}
|
|
104
|
+
const data = await response.json();
|
|
105
|
+
return (data.data || []).map((item) => item.value);
|
|
106
|
+
} catch {
|
|
107
|
+
return [];
|
|
108
|
+
}
|
|
109
|
+
}, [filterBy, debouncedSearch, api, tags]);
|
|
110
|
+
const { value: tagValuesData, loading: isLoadingTagValues } = useAsync(async () => {
|
|
111
|
+
if (filterBy === "tag" && selectedTagKey) {
|
|
112
|
+
try {
|
|
113
|
+
const timeScopeValue = timeRange === "month-to-date" ? -1 : -2;
|
|
114
|
+
const response = await api.getOpenShiftTagValues(
|
|
115
|
+
selectedTagKey,
|
|
116
|
+
timeScopeValue
|
|
117
|
+
);
|
|
118
|
+
const data = await response.json();
|
|
119
|
+
const allValues = /* @__PURE__ */ new Set();
|
|
120
|
+
for (const item of data.data || []) {
|
|
121
|
+
if (item.values) {
|
|
122
|
+
for (const value of item.values) {
|
|
123
|
+
allValues.add(value);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return Array.from(allValues).sort(
|
|
128
|
+
(a, b) => a.localeCompare(b, "en-US")
|
|
129
|
+
);
|
|
130
|
+
} catch {
|
|
131
|
+
return [];
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return [];
|
|
135
|
+
}, [filterBy, selectedTagKey, timeRange, api]);
|
|
136
|
+
const getFilterValueOptions = useMemo(() => {
|
|
137
|
+
const options = resourceOptions || [];
|
|
138
|
+
if (filterValue && !options.includes(filterValue)) {
|
|
139
|
+
return [filterValue, ...options];
|
|
140
|
+
}
|
|
141
|
+
return options;
|
|
142
|
+
}, [resourceOptions, filterValue]);
|
|
143
|
+
const handleInputChange = useCallback(
|
|
144
|
+
(_event, value, reason) => {
|
|
145
|
+
if (reason === "input") {
|
|
146
|
+
setSearchInput(value);
|
|
147
|
+
}
|
|
148
|
+
},
|
|
149
|
+
[]
|
|
150
|
+
);
|
|
151
|
+
const currencyOptions = [
|
|
152
|
+
{ label: "AUD (A$) - Australian Dollar", value: "AUD" },
|
|
153
|
+
{ label: "BRL (R$) - Brazilian Real", value: "BRL" },
|
|
154
|
+
{ label: "CAD (CA$) - Canadian Dollar", value: "CAD" },
|
|
155
|
+
{ label: "CHF (CHF) - Swiss Franc", value: "CHF" },
|
|
156
|
+
{ label: "CNY (CN\xA5) - Chinese Yuan", value: "CNY" },
|
|
157
|
+
{ label: "CZK (K\u010D) - Czech Koruna", value: "CZK" },
|
|
158
|
+
{ label: "DKK (DKK) - Danish Krone", value: "DKK" },
|
|
159
|
+
{ label: "EUR (\u20AC) - Euro", value: "EUR" },
|
|
160
|
+
{ label: "GBP (\xA3) - British Pound", value: "GBP" },
|
|
161
|
+
{ label: "HKD (HK$) - Hong Kong Dollar", value: "HKD" },
|
|
162
|
+
{ label: "INR (\u20B9) - Indian Rupee", value: "INR" },
|
|
163
|
+
{ label: "JPY (\xA5) - Japanese Yen", value: "JPY" },
|
|
164
|
+
{ label: "NGN (\u20A6) - Nigerian Naira", value: "NGN" },
|
|
165
|
+
{ label: "NOK (NOK) - Norwegian Krone", value: "NOK" },
|
|
166
|
+
{ label: "NZD (NZ$) - New Zealand Dollar", value: "NZD" },
|
|
167
|
+
{ label: "SEK (SEK) - Swedish Krona", value: "SEK" },
|
|
168
|
+
{ label: "SGD (SGD) - Singapore Dollar", value: "SGD" },
|
|
169
|
+
{ label: "USD ($) - United States Dollar", value: "USD" },
|
|
170
|
+
{ label: "ZAR (ZAR) - South African Rand", value: "ZAR" }
|
|
171
|
+
];
|
|
172
|
+
return /* @__PURE__ */ React.createElement(Box, { className: baseClasses.root }, /* @__PURE__ */ React.createElement(Box, { className: `${baseClasses.filters} ${classes.filters}` }, /* @__PURE__ */ React.createElement("div", { className: classes.filterSection }, /* @__PURE__ */ React.createElement(Box, { p: 1, pt: 0 }, /* @__PURE__ */ React.createElement(
|
|
173
|
+
SelectComponent,
|
|
174
|
+
{
|
|
175
|
+
freeSolo: true,
|
|
176
|
+
selectOnFocus: true,
|
|
177
|
+
clearOnBlur: true,
|
|
178
|
+
handleHomeEndKeys: true,
|
|
179
|
+
filterSelectedOptions: true,
|
|
180
|
+
label: "Group by",
|
|
181
|
+
options: ["project", "cluster", "node", "tag"],
|
|
182
|
+
value: groupBy,
|
|
183
|
+
placeholder: "Group by",
|
|
184
|
+
onChange: (event) => onGroupByChange(event.target.value)
|
|
185
|
+
}
|
|
186
|
+
), groupBy === "tag" && /* @__PURE__ */ React.createElement(Box, { p: 0, pt: 0 }, /* @__PURE__ */ React.createElement(
|
|
187
|
+
AutocompleteComponent,
|
|
188
|
+
{
|
|
189
|
+
label: "Choose key",
|
|
190
|
+
options: tags,
|
|
191
|
+
value: selectedTag,
|
|
192
|
+
placeholder: "Choose key",
|
|
193
|
+
loading: false,
|
|
194
|
+
onChange: (_event, value) => {
|
|
195
|
+
onSelectedTagChange(value ?? "");
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
)))), /* @__PURE__ */ React.createElement("div", { className: classes.filterSection }, /* @__PURE__ */ React.createElement(Box, { p: 1 }, /* @__PURE__ */ React.createElement(
|
|
199
|
+
SelectComponent,
|
|
200
|
+
{
|
|
201
|
+
freeSolo: true,
|
|
202
|
+
selectOnFocus: true,
|
|
203
|
+
clearOnBlur: true,
|
|
204
|
+
handleHomeEndKeys: true,
|
|
205
|
+
filterSelectedOptions: true,
|
|
206
|
+
label: "Overhead cost",
|
|
207
|
+
options: [
|
|
208
|
+
"Distribute through cost models",
|
|
209
|
+
"Don't distribute overhead costs"
|
|
210
|
+
],
|
|
211
|
+
value: overheadDistribution === "distribute" ? "Distribute through cost models" : "Don't distribute overhead costs",
|
|
212
|
+
placeholder: "Overhead cost",
|
|
213
|
+
onChange: (event) => {
|
|
214
|
+
const value = event.target.value;
|
|
215
|
+
const mappedValue = value === "Distribute through cost models" ? "distribute" : "dont_distribute";
|
|
216
|
+
onOverheadDistributionChange(mappedValue);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
))), /* @__PURE__ */ React.createElement("div", { className: classes.filterSection }, /* @__PURE__ */ React.createElement(Box, { p: 1 }, /* @__PURE__ */ React.createElement(
|
|
220
|
+
SelectComponent,
|
|
221
|
+
{
|
|
222
|
+
freeSolo: true,
|
|
223
|
+
selectOnFocus: true,
|
|
224
|
+
clearOnBlur: true,
|
|
225
|
+
handleHomeEndKeys: true,
|
|
226
|
+
filterSelectedOptions: true,
|
|
227
|
+
label: "Time",
|
|
228
|
+
options: ["Month to date", "Previous month"],
|
|
229
|
+
value: timeRange === "month-to-date" ? "Month to date" : "Previous month",
|
|
230
|
+
placeholder: "Time",
|
|
231
|
+
onChange: (event) => {
|
|
232
|
+
const value = event.target.value;
|
|
233
|
+
const mappedValue = value === "Month to date" ? "month-to-date" : "previous-month";
|
|
234
|
+
onTimeRangeChange(mappedValue);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
))), /* @__PURE__ */ React.createElement(Box, { marginX: 2 }, /* @__PURE__ */ React.createElement(Divider, { className: classes.divider })), /* @__PURE__ */ React.createElement("div", { className: classes.filterSection }, /* @__PURE__ */ React.createElement(
|
|
238
|
+
"div",
|
|
239
|
+
{
|
|
240
|
+
style: {
|
|
241
|
+
backgroundColor: filterTableBackgroundColor,
|
|
242
|
+
padding: 16,
|
|
243
|
+
borderRadius: 8
|
|
244
|
+
}
|
|
245
|
+
},
|
|
246
|
+
/* @__PURE__ */ React.createElement("div", { style: { fontWeight: "bold", marginBottom: "8px" } }, "Filter table by"),
|
|
247
|
+
/* @__PURE__ */ React.createElement(
|
|
248
|
+
SelectComponent,
|
|
249
|
+
{
|
|
250
|
+
freeSolo: true,
|
|
251
|
+
selectOnFocus: true,
|
|
252
|
+
clearOnBlur: true,
|
|
253
|
+
handleHomeEndKeys: true,
|
|
254
|
+
filterSelectedOptions: true,
|
|
255
|
+
label: "",
|
|
256
|
+
options: ["project", "cluster", "node", "tag"],
|
|
257
|
+
value: filterBy,
|
|
258
|
+
placeholder: "",
|
|
259
|
+
onChange: (event) => {
|
|
260
|
+
const newFilterBy = event.target.value;
|
|
261
|
+
onFilterByChange(newFilterBy);
|
|
262
|
+
onFilterValueChange("");
|
|
263
|
+
if (newFilterBy !== "tag") {
|
|
264
|
+
onSelectedTagKeyChange("");
|
|
265
|
+
onSelectedTagValueChange("");
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
),
|
|
270
|
+
/* @__PURE__ */ React.createElement(
|
|
271
|
+
SelectComponent,
|
|
272
|
+
{
|
|
273
|
+
freeSolo: true,
|
|
274
|
+
selectOnFocus: true,
|
|
275
|
+
clearOnBlur: true,
|
|
276
|
+
handleHomeEndKeys: true,
|
|
277
|
+
filterSelectedOptions: true,
|
|
278
|
+
label: "",
|
|
279
|
+
options: ["includes", "excludes", "exact"],
|
|
280
|
+
value: filterOperation,
|
|
281
|
+
placeholder: "",
|
|
282
|
+
onChange: (event) => {
|
|
283
|
+
onFilterOperationChange(event.target.value);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
),
|
|
287
|
+
filterBy === "tag" ? /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(
|
|
288
|
+
AutocompleteComponent,
|
|
289
|
+
{
|
|
290
|
+
label: "",
|
|
291
|
+
options: getFilterValueOptions,
|
|
292
|
+
value: selectedTagKey,
|
|
293
|
+
placeholder: "Select tag key",
|
|
294
|
+
loading: false,
|
|
295
|
+
onInputChange: handleInputChange,
|
|
296
|
+
onChange: (_event, value) => {
|
|
297
|
+
const tagKey = value ?? "";
|
|
298
|
+
onSelectedTagKeyChange(tagKey);
|
|
299
|
+
onSelectedTagValueChange("");
|
|
300
|
+
setSearchInput("");
|
|
301
|
+
setDebouncedSearch("");
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
), selectedTagKey && /* @__PURE__ */ React.createElement(Box, { style: { marginTop: "-8px" } }, /* @__PURE__ */ React.createElement(
|
|
305
|
+
AutocompleteComponent,
|
|
306
|
+
{
|
|
307
|
+
label: "",
|
|
308
|
+
options: tagValuesData || [],
|
|
309
|
+
value: selectedTagValue,
|
|
310
|
+
placeholder: "Select tag value",
|
|
311
|
+
loading: isLoadingTagValues,
|
|
312
|
+
onChange: (_event, value) => {
|
|
313
|
+
onSelectedTagValueChange(value ?? "");
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
))) : /* @__PURE__ */ React.createElement(
|
|
317
|
+
AutocompleteComponent,
|
|
318
|
+
{
|
|
319
|
+
label: "",
|
|
320
|
+
options: getFilterValueOptions,
|
|
321
|
+
value: filterValue,
|
|
322
|
+
placeholder: `Filter by ${filterBy || "project"}`,
|
|
323
|
+
loading: isLoadingOptions,
|
|
324
|
+
onInputChange: handleInputChange,
|
|
325
|
+
onChange: (_event, value) => {
|
|
326
|
+
onFilterValueChange(value ?? "");
|
|
327
|
+
setSearchInput("");
|
|
328
|
+
setDebouncedSearch("");
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
)
|
|
332
|
+
)), /* @__PURE__ */ React.createElement(Box, { marginX: 2 }, /* @__PURE__ */ React.createElement(Divider, { className: classes.divider })), /* @__PURE__ */ React.createElement("div", { className: classes.filterSection }, /* @__PURE__ */ React.createElement(Box, { p: 2 }, /* @__PURE__ */ React.createElement(
|
|
333
|
+
SelectComponent,
|
|
334
|
+
{
|
|
335
|
+
freeSolo: true,
|
|
336
|
+
selectOnFocus: true,
|
|
337
|
+
clearOnBlur: true,
|
|
338
|
+
handleHomeEndKeys: true,
|
|
339
|
+
filterSelectedOptions: true,
|
|
340
|
+
label: "Currency",
|
|
341
|
+
options: currencyOptions.map(
|
|
342
|
+
(value) => value.label
|
|
343
|
+
),
|
|
344
|
+
value: currencyOptions.find(
|
|
345
|
+
(item) => item.value === currency
|
|
346
|
+
)?.label ?? "",
|
|
347
|
+
placeholder: "Select currency",
|
|
348
|
+
onChange: (event) => {
|
|
349
|
+
const selectedLabel = event.target.value;
|
|
350
|
+
const selectedCurrency = currencyOptions.find(
|
|
351
|
+
(item) => item.label === selectedLabel
|
|
352
|
+
)?.value ?? "";
|
|
353
|
+
onCurrencyChange(selectedCurrency);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
)))));
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
export { Filters };
|
|
360
|
+
//# sourceMappingURL=Filters.esm.js.map
|