@openchoreo/backstage-plugin-openchoreo-observability 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +5 -0
- package/README.md +22 -0
- package/dist/api/FinOpsAgentApi.esm.js +43 -0
- package/dist/api/FinOpsAgentApi.esm.js.map +1 -0
- package/dist/api/ObservabilityApi.esm.js +568 -0
- package/dist/api/ObservabilityApi.esm.js.map +1 -0
- package/dist/api/ObserverUrlCache.esm.js +59 -0
- package/dist/api/ObserverUrlCache.esm.js.map +1 -0
- package/dist/api/RCAAgentApi.esm.js +104 -0
- package/dist/api/RCAAgentApi.esm.js.map +1 -0
- package/dist/components/Alerts/AlertRow.esm.js +203 -0
- package/dist/components/Alerts/AlertRow.esm.js.map +1 -0
- package/dist/components/Alerts/AlertsActions.esm.js +77 -0
- package/dist/components/Alerts/AlertsActions.esm.js.map +1 -0
- package/dist/components/Alerts/AlertsFilter.esm.js +95 -0
- package/dist/components/Alerts/AlertsFilter.esm.js.map +1 -0
- package/dist/components/Alerts/AlertsTable.esm.js +63 -0
- package/dist/components/Alerts/AlertsTable.esm.js.map +1 -0
- package/dist/components/Alerts/ObservabilityAlertsPage.esm.js +251 -0
- package/dist/components/Alerts/ObservabilityAlertsPage.esm.js.map +1 -0
- package/dist/components/Alerts/types.esm.js +4 -0
- package/dist/components/Alerts/types.esm.js.map +1 -0
- package/dist/components/CostAnalysis/CostAnalysisPage.esm.js +141 -0
- package/dist/components/CostAnalysis/CostAnalysisPage.esm.js.map +1 -0
- package/dist/components/CostAnalysis/CostAnalysisReport.esm.js +128 -0
- package/dist/components/CostAnalysis/CostAnalysisReport.esm.js.map +1 -0
- package/dist/components/CostAnalysis/CostAnalysisReportView.esm.js +517 -0
- package/dist/components/CostAnalysis/CostAnalysisReportView.esm.js.map +1 -0
- package/dist/components/CostAnalysis/CostAnalysisTable.esm.js +149 -0
- package/dist/components/CostAnalysis/CostAnalysisTable.esm.js.map +1 -0
- package/dist/components/CostAnalysis/FinOpsApplyButton.esm.js +112 -0
- package/dist/components/CostAnalysis/FinOpsApplyButton.esm.js.map +1 -0
- package/dist/components/CostAnalysis/index.esm.js +2 -0
- package/dist/components/CostAnalysis/index.esm.js.map +1 -0
- package/dist/components/Incidents/IncidentRow.esm.js +258 -0
- package/dist/components/Incidents/IncidentRow.esm.js.map +1 -0
- package/dist/components/Incidents/IncidentsActions.esm.js +77 -0
- package/dist/components/Incidents/IncidentsActions.esm.js.map +1 -0
- package/dist/components/Incidents/IncidentsFilter.esm.js +144 -0
- package/dist/components/Incidents/IncidentsFilter.esm.js.map +1 -0
- package/dist/components/Incidents/IncidentsTable.esm.js +68 -0
- package/dist/components/Incidents/IncidentsTable.esm.js.map +1 -0
- package/dist/components/Incidents/ObservabilityProjectIncidentsPage.esm.js +283 -0
- package/dist/components/Incidents/ObservabilityProjectIncidentsPage.esm.js.map +1 -0
- package/dist/components/Incidents/types.esm.js +8 -0
- package/dist/components/Incidents/types.esm.js.map +1 -0
- package/dist/components/Metrics/ChartTooltip.esm.js +53 -0
- package/dist/components/Metrics/ChartTooltip.esm.js.map +1 -0
- package/dist/components/Metrics/HTTPMetricsSection.esm.js +109 -0
- package/dist/components/Metrics/HTTPMetricsSection.esm.js.map +1 -0
- package/dist/components/Metrics/MetricGraphByComponent.esm.js +99 -0
- package/dist/components/Metrics/MetricGraphByComponent.esm.js.map +1 -0
- package/dist/components/Metrics/MetricsActions.esm.js +30 -0
- package/dist/components/Metrics/MetricsActions.esm.js.map +1 -0
- package/dist/components/Metrics/MetricsFilters.esm.js +49 -0
- package/dist/components/Metrics/MetricsFilters.esm.js.map +1 -0
- package/dist/components/Metrics/ObservabilityMetricsPage.esm.js +196 -0
- package/dist/components/Metrics/ObservabilityMetricsPage.esm.js.map +1 -0
- package/dist/components/Metrics/styles.esm.js +55 -0
- package/dist/components/Metrics/styles.esm.js.map +1 -0
- package/dist/components/Metrics/utils.esm.js +221 -0
- package/dist/components/Metrics/utils.esm.js.map +1 -0
- package/dist/components/RCA/RCAActions.esm.js +42 -0
- package/dist/components/RCA/RCAActions.esm.js.map +1 -0
- package/dist/components/RCA/RCAFilters.esm.js +100 -0
- package/dist/components/RCA/RCAFilters.esm.js.map +1 -0
- package/dist/components/RCA/RCAPage.esm.js +137 -0
- package/dist/components/RCA/RCAPage.esm.js.map +1 -0
- package/dist/components/RCA/RCAReport/EntityLinkContext.esm.js +9 -0
- package/dist/components/RCA/RCAReport/EntityLinkContext.esm.js.map +1 -0
- package/dist/components/RCA/RCAReport/FormattedText.esm.js +94 -0
- package/dist/components/RCA/RCAReport/FormattedText.esm.js.map +1 -0
- package/dist/components/RCA/RCAReport/RCAReportView.esm.js +308 -0
- package/dist/components/RCA/RCAReport/RCAReportView.esm.js.map +1 -0
- package/dist/components/RCA/RCAReport/sections/AssessmentSection.esm.js +113 -0
- package/dist/components/RCA/RCAReport/sections/AssessmentSection.esm.js.map +1 -0
- package/dist/components/RCA/RCAReport/sections/ChatPanelSection.esm.js +272 -0
- package/dist/components/RCA/RCAReport/sections/ChatPanelSection.esm.js.map +1 -0
- package/dist/components/RCA/RCAReport/sections/ExcludedCausesSection.esm.js +48 -0
- package/dist/components/RCA/RCAReport/sections/ExcludedCausesSection.esm.js.map +1 -0
- package/dist/components/RCA/RCAReport/sections/IncidentOverviewSection.esm.js +205 -0
- package/dist/components/RCA/RCAReport/sections/IncidentOverviewSection.esm.js.map +1 -0
- package/dist/components/RCA/RCAReport/sections/InvestigationPathSection.esm.js +121 -0
- package/dist/components/RCA/RCAReport/sections/InvestigationPathSection.esm.js.map +1 -0
- package/dist/components/RCA/RCAReport/sections/PatchTabContent.esm.js +593 -0
- package/dist/components/RCA/RCAReport/sections/PatchTabContent.esm.js.map +1 -0
- package/dist/components/RCA/RCAReport/sections/QuickFixesPanelSection.esm.js +35 -0
- package/dist/components/RCA/RCAReport/sections/QuickFixesPanelSection.esm.js.map +1 -0
- package/dist/components/RCA/RCAReport/sections/RecommendationsSection.esm.js +54 -0
- package/dist/components/RCA/RCAReport/sections/RecommendationsSection.esm.js.map +1 -0
- package/dist/components/RCA/RCAReport/sections/RootCausesSection.esm.js +526 -0
- package/dist/components/RCA/RCAReport/sections/RootCausesSection.esm.js.map +1 -0
- package/dist/components/RCA/RCAReport/sections/SystemTimelineSection.esm.js +70 -0
- package/dist/components/RCA/RCAReport/sections/SystemTimelineSection.esm.js.map +1 -0
- package/dist/components/RCA/RCAReport/sections/VisibilityImprovementsSection.esm.js +54 -0
- package/dist/components/RCA/RCAReport/sections/VisibilityImprovementsSection.esm.js.map +1 -0
- package/dist/components/RCA/RCAReport/styles.esm.js +467 -0
- package/dist/components/RCA/RCAReport/styles.esm.js.map +1 -0
- package/dist/components/RCA/RCAReport.esm.js +109 -0
- package/dist/components/RCA/RCAReport.esm.js.map +1 -0
- package/dist/components/RCA/RCATable.esm.js +140 -0
- package/dist/components/RCA/RCATable.esm.js.map +1 -0
- package/dist/components/RuntimeLogs/LogEntry.esm.js +182 -0
- package/dist/components/RuntimeLogs/LogEntry.esm.js.map +1 -0
- package/dist/components/RuntimeLogs/LogsActions.esm.js +106 -0
- package/dist/components/RuntimeLogs/LogsActions.esm.js.map +1 -0
- package/dist/components/RuntimeLogs/LogsFilter.esm.js +200 -0
- package/dist/components/RuntimeLogs/LogsFilter.esm.js.map +1 -0
- package/dist/components/RuntimeLogs/LogsTable.esm.js +91 -0
- package/dist/components/RuntimeLogs/LogsTable.esm.js.map +1 -0
- package/dist/components/RuntimeLogs/ObservabilityProjectRuntimeLogsPage.esm.js +220 -0
- package/dist/components/RuntimeLogs/ObservabilityProjectRuntimeLogsPage.esm.js.map +1 -0
- package/dist/components/RuntimeLogs/ObservabilityRuntimeLogsPage.esm.js +222 -0
- package/dist/components/RuntimeLogs/ObservabilityRuntimeLogsPage.esm.js.map +1 -0
- package/dist/components/RuntimeLogs/styles.esm.js +256 -0
- package/dist/components/RuntimeLogs/styles.esm.js.map +1 -0
- package/dist/components/RuntimeLogs/types.esm.js +16 -0
- package/dist/components/RuntimeLogs/types.esm.js.map +1 -0
- package/dist/components/TimeRangeFilter/TimeRangeFilter.esm.js +280 -0
- package/dist/components/TimeRangeFilter/TimeRangeFilter.esm.js.map +1 -0
- package/dist/components/Traces/ObservabilityTracesPage.esm.js +165 -0
- package/dist/components/Traces/ObservabilityTracesPage.esm.js.map +1 -0
- package/dist/components/Traces/TracesActions.esm.js +37 -0
- package/dist/components/Traces/TracesActions.esm.js.map +1 -0
- package/dist/components/Traces/TracesFilters.esm.js +121 -0
- package/dist/components/Traces/TracesFilters.esm.js.map +1 -0
- package/dist/components/Traces/TracesTable.esm.js +137 -0
- package/dist/components/Traces/TracesTable.esm.js.map +1 -0
- package/dist/components/Traces/WaterfallView.esm.js +567 -0
- package/dist/components/Traces/WaterfallView.esm.js.map +1 -0
- package/dist/components/Traces/styles.esm.js +198 -0
- package/dist/components/Traces/styles.esm.js.map +1 -0
- package/dist/components/Traces/utils.esm.js +19 -0
- package/dist/components/Traces/utils.esm.js.map +1 -0
- package/dist/hooks/useAutoSelectFirstEnvironment.esm.js +25 -0
- package/dist/hooks/useAutoSelectFirstEnvironment.esm.js.map +1 -0
- package/dist/hooks/useComponentAlerts.esm.js +80 -0
- package/dist/hooks/useComponentAlerts.esm.js.map +1 -0
- package/dist/hooks/useDataPlaneNetPolProvider.esm.js +55 -0
- package/dist/hooks/useDataPlaneNetPolProvider.esm.js.map +1 -0
- package/dist/hooks/useDebouncedSearch.esm.js +24 -0
- package/dist/hooks/useDebouncedSearch.esm.js.map +1 -0
- package/dist/hooks/useFilters.esm.js +29 -0
- package/dist/hooks/useFilters.esm.js.map +1 -0
- package/dist/hooks/useFinOpsReport.esm.js +66 -0
- package/dist/hooks/useFinOpsReport.esm.js.map +1 -0
- package/dist/hooks/useFinOpsReports.esm.js +70 -0
- package/dist/hooks/useFinOpsReports.esm.js.map +1 -0
- package/dist/hooks/useGetComponentsByProject.esm.js +57 -0
- package/dist/hooks/useGetComponentsByProject.esm.js.map +1 -0
- package/dist/hooks/useGetEnvironmentsByNamespace.esm.js +53 -0
- package/dist/hooks/useGetEnvironmentsByNamespace.esm.js.map +1 -0
- package/dist/hooks/useGetNamespaceAndProjectByEntity.esm.js +40 -0
- package/dist/hooks/useGetNamespaceAndProjectByEntity.esm.js.map +1 -0
- package/dist/hooks/useMetrics.esm.js +107 -0
- package/dist/hooks/useMetrics.esm.js.map +1 -0
- package/dist/hooks/useProjectIncidents.esm.js +111 -0
- package/dist/hooks/useProjectIncidents.esm.js.map +1 -0
- package/dist/hooks/useProjectRuntimeLogs.esm.js +185 -0
- package/dist/hooks/useProjectRuntimeLogs.esm.js.map +1 -0
- package/dist/hooks/useRCAReportByAlert.esm.js +54 -0
- package/dist/hooks/useRCAReportByAlert.esm.js.map +1 -0
- package/dist/hooks/useRCAReports.esm.js +75 -0
- package/dist/hooks/useRCAReports.esm.js.map +1 -0
- package/dist/hooks/useRuntimeLogs.esm.js +147 -0
- package/dist/hooks/useRuntimeLogs.esm.js.map +1 -0
- package/dist/hooks/useSpanDetails.esm.js +71 -0
- package/dist/hooks/useSpanDetails.esm.js.map +1 -0
- package/dist/hooks/useTraceSpans.esm.js +80 -0
- package/dist/hooks/useTraceSpans.esm.js.map +1 -0
- package/dist/hooks/useTraces.esm.js +112 -0
- package/dist/hooks/useTraces.esm.js.map +1 -0
- package/dist/hooks/useUpdateIncident.esm.js +50 -0
- package/dist/hooks/useUpdateIncident.esm.js.map +1 -0
- package/dist/hooks/useUrlFilters.esm.js +63 -0
- package/dist/hooks/useUrlFilters.esm.js.map +1 -0
- package/dist/hooks/useUrlFiltersForAlerts.esm.js +80 -0
- package/dist/hooks/useUrlFiltersForAlerts.esm.js.map +1 -0
- package/dist/hooks/useUrlFiltersForIncidents.esm.js +87 -0
- package/dist/hooks/useUrlFiltersForIncidents.esm.js.map +1 -0
- package/dist/hooks/useUrlFiltersForRuntimeLogs.esm.js +135 -0
- package/dist/hooks/useUrlFiltersForRuntimeLogs.esm.js.map +1 -0
- package/dist/index.d.ts +41 -0
- package/dist/index.esm.js +2 -0
- package/dist/index.esm.js.map +1 -0
- package/dist/plugin.esm.js +107 -0
- package/dist/plugin.esm.js.map +1 -0
- package/dist/routes.esm.js +8 -0
- package/dist/routes.esm.js.map +1 -0
- package/dist/types.esm.js +18 -0
- package/dist/types.esm.js.map +1 -0
- package/dist/utils/applyResourceChange.esm.js +79 -0
- package/dist/utils/applyResourceChange.esm.js.map +1 -0
- package/dist/utils/urlTimeRange.esm.js +52 -0
- package/dist/utils/urlTimeRange.esm.js.map +1 -0
- package/package.json +81 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ObservabilityProjectIncidentsPage.esm.js","sources":["../../../src/components/Incidents/ObservabilityProjectIncidentsPage.tsx"],"sourcesContent":["import { useEffect, useRef, useMemo, useState, useCallback } from 'react';\nimport { Box, Typography, Button, Snackbar } from '@material-ui/core';\nimport { EmptyState, Progress, WarningIcon } from '@backstage/core-components';\nimport { Alert } from '@material-ui/lab';\nimport { useEntity } from '@backstage/plugin-catalog-react';\nimport { CHOREO_ANNOTATIONS } from '@openchoreo/backstage-plugin-common';\nimport { IncidentsFilter } from './IncidentsFilter';\nimport { IncidentsTable } from './IncidentsTable';\nimport { IncidentsActions } from './IncidentsActions';\nimport {\n useGetEnvironmentsByNamespace,\n useGetComponentsByProject,\n useProjectIncidents,\n useUrlFiltersForIncidents,\n useUpdateIncident,\n} from '../../hooks';\nimport { useIncidentsPermission } from '@openchoreo/backstage-plugin-react';\nimport { useRuntimeLogsStyles } from '../RuntimeLogs/styles';\nimport type { IncidentSummary } from '../../types';\n\nconst ObservabilityProjectIncidentsContent = () => {\n const classes = useRuntimeLogsStyles();\n const { entity } = useEntity();\n\n const namespace =\n entity.metadata.annotations?.[CHOREO_ANNOTATIONS.NAMESPACE] || '';\n const projectName = entity.metadata.name || '';\n\n const {\n environments,\n loading: environmentsLoading,\n error: environmentsError,\n } = useGetEnvironmentsByNamespace(namespace, projectName);\n\n const {\n components,\n loading: componentsLoading,\n error: componentsError,\n } = useGetComponentsByProject(entity);\n\n const { filters, updateFilters } = useUrlFiltersForIncidents({\n environments,\n });\n\n const selectedEnvironment = environments.find(\n env => env.name === filters.environment,\n );\n\n const [lastUpdated, setLastUpdated] = useState<Date>(new Date());\n const [updatingIncidentId, setUpdatingIncidentId] = useState<string | null>(\n null,\n );\n const [snackbarMessage, setSnackbarMessage] = useState<string | null>(null);\n\n const { updateIncident } = useUpdateIncident();\n\n const {\n incidents,\n loading: incidentsLoading,\n error: incidentsError,\n fetchIncidents,\n refresh,\n } = useProjectIncidents(entity, {\n environment: filters.environment,\n timeRange: filters.timeRange,\n customStartTime: filters.customStartTime,\n customEndTime: filters.customEndTime,\n components: filters.components,\n sortOrder: filters.sortOrder || 'desc',\n });\n\n const previousFiltersRef = useRef<{\n environment: string;\n timeRange: string;\n customStartTime?: string;\n customEndTime?: string;\n components: string[];\n sortOrder?: 'asc' | 'desc';\n } | null>(null);\n\n useEffect(() => {\n const currentFilters = {\n environment: filters.environment,\n timeRange: filters.timeRange,\n customStartTime: filters.customStartTime,\n customEndTime: filters.customEndTime,\n components: filters.components || [],\n sortOrder: filters.sortOrder,\n };\n const filtersChanged =\n previousFiltersRef.current === null ||\n JSON.stringify(previousFiltersRef.current) !==\n JSON.stringify(currentFilters);\n\n if (\n filters.environment &&\n selectedEnvironment &&\n namespace &&\n projectName &&\n filtersChanged\n ) {\n fetchIncidents(true);\n setLastUpdated(new Date());\n previousFiltersRef.current = currentFilters;\n }\n }, [\n filters.environment,\n filters.timeRange,\n filters.customStartTime,\n filters.customEndTime,\n filters.components,\n filters.sortOrder,\n fetchIncidents,\n selectedEnvironment,\n namespace,\n projectName,\n ]);\n\n useEffect(() => {\n if (!incidentsLoading) setLastUpdated(new Date());\n }, [incidentsLoading]);\n\n const handleRefresh = () => {\n refresh();\n setLastUpdated(new Date());\n };\n\n const handleFiltersChange = (newFilters: Partial<typeof filters>) => {\n updateFilters(newFilters);\n };\n\n const filteredIncidents = useMemo((): IncidentSummary[] => {\n let result = incidents;\n if (filters.status && filters.status.length > 0) {\n result = result.filter(\n i =>\n i.status &&\n filters.status!.some(\n s => s.toLowerCase() === (i.status || '').toLowerCase(),\n ),\n );\n }\n if (filters.searchQuery) {\n const q = filters.searchQuery.toLowerCase();\n result = result.filter(\n i =>\n (i.description || '').toLowerCase().includes(q) ||\n (i.incidentId || '').toLowerCase().includes(q) ||\n (i.alertId || '').toLowerCase().includes(q) ||\n (i.componentName || '').toLowerCase().includes(q),\n );\n }\n return result;\n }, [incidents, filters.status, filters.searchQuery]);\n\n // Open the RCA Reports tab of this project entity in a new browser tab,\n // pre-filtered by environment, time range, and alert ID.\n const handleViewRCA = useCallback(\n (incident: IncidentSummary) => {\n const catalogNs = entity.metadata.namespace || 'default';\n const params = new URLSearchParams({\n ...(filters.environment ? { env: filters.environment } : {}),\n ...(filters.timeRange ? { timeRange: filters.timeRange } : {}),\n ...(incident.alertId ? { q: incident.alertId } : {}),\n });\n const query = params.toString();\n const url = `/catalog/${catalogNs}/system/${projectName}/rca-reports${\n query ? `?${query}` : ''\n }`;\n window.open(url, '_blank', 'noopener,noreferrer');\n },\n [entity, projectName, filters.environment, filters.timeRange],\n );\n\n // Open the Cost Analysis tab of this project entity in a new browser tab,\n // pre-filtered by environment and time range.\n const handleViewCostAnalysis = useCallback(\n (_incident: IncidentSummary) => {\n const catalogNs = entity.metadata.namespace || 'default';\n const params = new URLSearchParams({\n ...(filters.environment ? { env: filters.environment } : {}),\n ...(filters.timeRange ? { timeRange: filters.timeRange } : {}),\n });\n const query = params.toString();\n const url = `/catalog/${catalogNs}/system/${projectName}/cost-analysis${\n query ? `?${query}` : ''\n }`;\n window.open(url, '_blank', 'noopener,noreferrer');\n },\n [entity, projectName, filters.environment, filters.timeRange],\n );\n\n const handleAcknowledge = useCallback(\n async (incident: IncidentSummary) => {\n setUpdatingIncidentId(incident.incidentId);\n try {\n await updateIncident(incident, 'acknowledged');\n refresh();\n setLastUpdated(new Date());\n } catch (err) {\n const detail = err instanceof Error ? err.message : String(err);\n setSnackbarMessage(\n `Failed to acknowledge incident ${incident.incidentId}: ${detail}`,\n );\n } finally {\n setUpdatingIncidentId(null);\n }\n },\n [updateIncident, refresh],\n );\n\n const handleResolve = useCallback(\n async (incident: IncidentSummary) => {\n setUpdatingIncidentId(incident.incidentId);\n try {\n await updateIncident(incident, 'resolved');\n refresh();\n setLastUpdated(new Date());\n } catch (err) {\n const detail = err instanceof Error ? err.message : String(err);\n setSnackbarMessage(\n `Failed to resolve incident ${incident.incidentId}: ${detail}`,\n );\n } finally {\n setUpdatingIncidentId(null);\n }\n },\n [updateIncident, refresh],\n );\n\n const renderError = (error: string) => {\n const isObservabilityDisabled = error.includes(\n 'Observability is not enabled',\n );\n return (\n <Alert\n severity={isObservabilityDisabled ? 'info' : 'error'}\n className={classes.errorContainer}\n >\n <Typography variant=\"body1\">\n {isObservabilityDisabled\n ? 'Observability is not enabled for this project. Enable observability to view incidents.'\n : error}\n </Typography>\n {!isObservabilityDisabled && (\n <Button onClick={handleRefresh} color=\"inherit\" size=\"small\">\n Retry\n </Button>\n )}\n </Alert>\n );\n };\n\n if (environmentsError) {\n return <Box>{renderError(environmentsError)}</Box>;\n }\n\n if (componentsError) {\n return <Box>{renderError(componentsError)}</Box>;\n }\n\n return (\n <Box>\n <IncidentsFilter\n filters={filters}\n onFiltersChange={handleFiltersChange}\n environments={environments}\n environmentsLoading={environmentsLoading}\n components={components}\n componentsLoading={componentsLoading}\n disabled={incidentsLoading}\n />\n\n {incidentsError && renderError(incidentsError)}\n\n {!filters.environment &&\n !environmentsLoading &&\n environments.length === 0 && (\n <Alert severity=\"info\" className={classes.errorContainer}>\n <Typography variant=\"body1\">\n No environments found for this project.\n </Typography>\n </Alert>\n )}\n\n {filters.environment && (\n <>\n <IncidentsActions\n totalCount={filteredIncidents.length}\n disabled={incidentsLoading || !filters.environment}\n onRefresh={handleRefresh}\n filters={filters}\n onFiltersChange={handleFiltersChange}\n lastUpdated={lastUpdated}\n />\n\n <IncidentsTable\n incidents={filteredIncidents}\n loading={incidentsLoading}\n namespaceName={namespace}\n projectName={projectName}\n environmentName={\n selectedEnvironment?.displayName || selectedEnvironment?.name\n }\n onViewRCA={handleViewRCA}\n onViewCostAnalysis={handleViewCostAnalysis}\n onAcknowledge={handleAcknowledge}\n onResolve={handleResolve}\n updatingIncidentId={updatingIncidentId}\n />\n </>\n )}\n\n <Snackbar\n open={!!snackbarMessage}\n autoHideDuration={6000}\n onClose={() => setSnackbarMessage(null)}\n anchorOrigin={{ vertical: 'bottom', horizontal: 'center' }}\n >\n <Alert severity=\"error\" onClose={() => setSnackbarMessage(null)}>\n {snackbarMessage}\n </Alert>\n </Snackbar>\n </Box>\n );\n};\n\nexport const ObservabilityProjectIncidentsPage = () => {\n const {\n canViewIncidents,\n loading: permissionLoading,\n deniedTooltip,\n } = useIncidentsPermission();\n\n if (permissionLoading) return <Progress />;\n\n if (!canViewIncidents) {\n return (\n <EmptyState\n missing=\"data\"\n title=\"Permission Denied\"\n description={\n <Box display=\"flex\" alignItems=\"center\" gridGap={8}>\n <WarningIcon />\n {deniedTooltip}\n </Box>\n }\n />\n );\n }\n\n return <ObservabilityProjectIncidentsContent />;\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.esm.js","sources":["../../../src/components/Incidents/types.ts"],"sourcesContent":["export interface IncidentsFilters {\n environment: string;\n timeRange: string;\n /** ISO start time, used when `timeRange === 'custom'` */\n customStartTime?: string;\n /** ISO end time, used when `timeRange === 'custom'` */\n customEndTime?: string;\n components?: string[];\n sortOrder?: 'asc' | 'desc';\n status?: string[];\n searchQuery?: string;\n}\n\nexport const INCIDENT_STATUSES = [\n 'active',\n 'acknowledged',\n 'resolved',\n] as const;\n"],"names":[],"mappings":"AAaO,MAAM,iBAAA,GAAoB;AAAA,EAC/B,QAAA;AAAA,EACA,cAAA;AAAA,EACA;AACF;;;;"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { useTheme } from '@material-ui/core/styles';
|
|
3
|
+
|
|
4
|
+
const ChartTooltip = ({
|
|
5
|
+
active,
|
|
6
|
+
payload,
|
|
7
|
+
label,
|
|
8
|
+
labelFormatter,
|
|
9
|
+
formatter
|
|
10
|
+
}) => {
|
|
11
|
+
const theme = useTheme();
|
|
12
|
+
if (!active || !payload?.length) return null;
|
|
13
|
+
return /* @__PURE__ */ jsxs(
|
|
14
|
+
"div",
|
|
15
|
+
{
|
|
16
|
+
style: {
|
|
17
|
+
background: theme.palette.background.paper,
|
|
18
|
+
border: `1px solid ${theme.palette.divider}`,
|
|
19
|
+
borderRadius: theme.shape.borderRadius,
|
|
20
|
+
padding: theme.spacing(1, 1.5)
|
|
21
|
+
},
|
|
22
|
+
children: [
|
|
23
|
+
/* @__PURE__ */ jsx(
|
|
24
|
+
"p",
|
|
25
|
+
{
|
|
26
|
+
style: {
|
|
27
|
+
margin: `0 0 ${theme.spacing(0.5)}px`,
|
|
28
|
+
color: theme.palette.text.secondary,
|
|
29
|
+
fontSize: 12
|
|
30
|
+
},
|
|
31
|
+
children: labelFormatter ? labelFormatter(label) : label
|
|
32
|
+
}
|
|
33
|
+
),
|
|
34
|
+
payload.map((entry) => /* @__PURE__ */ jsxs(
|
|
35
|
+
"p",
|
|
36
|
+
{
|
|
37
|
+
style: { margin: `${theme.spacing(0.5)}px 0`, color: entry.color },
|
|
38
|
+
children: [
|
|
39
|
+
entry.name,
|
|
40
|
+
" :",
|
|
41
|
+
" ",
|
|
42
|
+
formatter && entry.value !== void 0 ? formatter(entry.value) : entry.value
|
|
43
|
+
]
|
|
44
|
+
},
|
|
45
|
+
entry.dataKey
|
|
46
|
+
))
|
|
47
|
+
]
|
|
48
|
+
}
|
|
49
|
+
);
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export { ChartTooltip };
|
|
53
|
+
//# sourceMappingURL=ChartTooltip.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChartTooltip.esm.js","sources":["../../../src/components/Metrics/ChartTooltip.tsx"],"sourcesContent":["import { useTheme } from '@material-ui/core/styles';\n\ninterface TooltipEntry {\n dataKey?: string | number;\n name?: string;\n value?: number;\n color?: string;\n}\n\ninterface ChartTooltipProps {\n active?: boolean;\n payload?: TooltipEntry[];\n label?: any;\n labelFormatter?: (label: any) => string;\n formatter?: (value: number) => string;\n}\n\nexport const ChartTooltip = ({\n active,\n payload,\n label,\n labelFormatter,\n formatter,\n}: ChartTooltipProps) => {\n const theme = useTheme();\n\n if (!active || !payload?.length) return null;\n\n return (\n <div\n style={{\n background: theme.palette.background.paper,\n border: `1px solid ${theme.palette.divider}`,\n borderRadius: theme.shape.borderRadius,\n padding: theme.spacing(1, 1.5),\n }}\n >\n <p\n style={{\n margin: `0 0 ${theme.spacing(0.5)}px`,\n color: theme.palette.text.secondary,\n fontSize: 12,\n }}\n >\n {labelFormatter ? labelFormatter(label) : label}\n </p>\n {payload.map((entry: TooltipEntry) => (\n <p\n key={entry.dataKey}\n style={{ margin: `${theme.spacing(0.5)}px 0`, color: entry.color }}\n >\n {entry.name} :{' '}\n {formatter && entry.value !== undefined\n ? formatter(entry.value)\n : entry.value}\n </p>\n ))}\n </div>\n );\n};\n"],"names":[],"mappings":";;;AAiBO,MAAM,eAAe,CAAC;AAAA,EAC3B,MAAA;AAAA,EACA,OAAA;AAAA,EACA,KAAA;AAAA,EACA,cAAA;AAAA,EACA;AACF,CAAA,KAAyB;AACvB,EAAA,MAAM,QAAQ,QAAA,EAAS;AAEvB,EAAA,IAAI,CAAC,MAAA,IAAU,CAAC,OAAA,EAAS,QAAQ,OAAO,IAAA;AAExC,EAAA,uBACE,IAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,KAAA,EAAO;AAAA,QACL,UAAA,EAAY,KAAA,CAAM,OAAA,CAAQ,UAAA,CAAW,KAAA;AAAA,QACrC,MAAA,EAAQ,CAAA,UAAA,EAAa,KAAA,CAAM,OAAA,CAAQ,OAAO,CAAA,CAAA;AAAA,QAC1C,YAAA,EAAc,MAAM,KAAA,CAAM,YAAA;AAAA,QAC1B,OAAA,EAAS,KAAA,CAAM,OAAA,CAAQ,CAAA,EAAG,GAAG;AAAA,OAC/B;AAAA,MAEA,QAAA,EAAA;AAAA,wBAAA,GAAA;AAAA,UAAC,GAAA;AAAA,UAAA;AAAA,YACC,KAAA,EAAO;AAAA,cACL,MAAA,EAAQ,CAAA,IAAA,EAAO,KAAA,CAAM,OAAA,CAAQ,GAAG,CAAC,CAAA,EAAA,CAAA;AAAA,cACjC,KAAA,EAAO,KAAA,CAAM,OAAA,CAAQ,IAAA,CAAK,SAAA;AAAA,cAC1B,QAAA,EAAU;AAAA,aACZ;AAAA,YAEC,QAAA,EAAA,cAAA,GAAiB,cAAA,CAAe,KAAK,CAAA,GAAI;AAAA;AAAA,SAC5C;AAAA,QACC,OAAA,CAAQ,GAAA,CAAI,CAAC,KAAA,qBACZ,IAAA;AAAA,UAAC,GAAA;AAAA,UAAA;AAAA,YAEC,KAAA,EAAO,EAAE,MAAA,EAAQ,CAAA,EAAG,KAAA,CAAM,OAAA,CAAQ,GAAG,CAAC,CAAA,IAAA,CAAA,EAAQ,KAAA,EAAO,KAAA,CAAM,KAAA,EAAM;AAAA,YAEhE,QAAA,EAAA;AAAA,cAAA,KAAA,CAAM,IAAA;AAAA,cAAK,IAAA;AAAA,cAAG,GAAA;AAAA,cACd,SAAA,IAAa,MAAM,KAAA,KAAU,MAAA,GAC1B,UAAU,KAAA,CAAM,KAAK,IACrB,KAAA,CAAM;AAAA;AAAA,WAAA;AAAA,UANL,KAAA,CAAM;AAAA,SAQd;AAAA;AAAA;AAAA,GACH;AAEJ;;;;"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
2
|
+
import { useRef, useEffect } from 'react';
|
|
3
|
+
import { Grid, Typography, Button, Card, CardHeader, Divider, CardContent } from '@material-ui/core';
|
|
4
|
+
import { Alert } from '@material-ui/lab';
|
|
5
|
+
import { MetricGraphByComponent } from './MetricGraphByComponent.esm.js';
|
|
6
|
+
import '@openchoreo/backstage-plugin-common';
|
|
7
|
+
import { useDataPlaneNetPolProvider } from '../../hooks/useDataPlaneNetPolProvider.esm.js';
|
|
8
|
+
import '@backstage/core-plugin-api';
|
|
9
|
+
import 'react-router-dom';
|
|
10
|
+
import '../../utils/urlTimeRange.esm.js';
|
|
11
|
+
import { useMetrics } from '../../hooks/useMetrics.esm.js';
|
|
12
|
+
import '../../api/ObservabilityApi.esm.js';
|
|
13
|
+
import '@openchoreo/backstage-plugin-react';
|
|
14
|
+
import '@backstage/plugin-catalog-react';
|
|
15
|
+
import '../../api/RCAAgentApi.esm.js';
|
|
16
|
+
import '../../api/FinOpsAgentApi.esm.js';
|
|
17
|
+
|
|
18
|
+
const HTTPMetricsSection = ({
|
|
19
|
+
filters,
|
|
20
|
+
entity,
|
|
21
|
+
namespaceName,
|
|
22
|
+
project
|
|
23
|
+
}) => {
|
|
24
|
+
const { networkPolicyProvider, loading: netPolLoading } = useDataPlaneNetPolProvider(
|
|
25
|
+
namespaceName,
|
|
26
|
+
filters.environment?.dataPlaneRef
|
|
27
|
+
);
|
|
28
|
+
const httpEnabled = networkPolicyProvider === "cilium";
|
|
29
|
+
const { metrics, error, fetchMetrics } = useMetrics(
|
|
30
|
+
filters,
|
|
31
|
+
entity,
|
|
32
|
+
namespaceName,
|
|
33
|
+
project,
|
|
34
|
+
"http"
|
|
35
|
+
);
|
|
36
|
+
const httpMetrics = metrics;
|
|
37
|
+
const previousFiltersRef = useRef({
|
|
38
|
+
environment: void 0,
|
|
39
|
+
timeRange: void 0
|
|
40
|
+
});
|
|
41
|
+
useEffect(() => {
|
|
42
|
+
if (!httpEnabled) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
const currentFilters = {
|
|
46
|
+
environment: filters.environment?.name,
|
|
47
|
+
timeRange: filters.timeRange
|
|
48
|
+
};
|
|
49
|
+
const filtersChanged = JSON.stringify(previousFiltersRef.current) !== JSON.stringify(currentFilters);
|
|
50
|
+
if (filters.environment && filters.timeRange && filtersChanged) {
|
|
51
|
+
fetchMetrics(true);
|
|
52
|
+
}
|
|
53
|
+
previousFiltersRef.current = currentFilters;
|
|
54
|
+
}, [httpEnabled, filters.environment, filters.timeRange, fetchMetrics]);
|
|
55
|
+
if (netPolLoading || !httpEnabled) {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
if (error) {
|
|
59
|
+
const isMetricsModuleError = error.toLowerCase().includes("metrics module");
|
|
60
|
+
return /* @__PURE__ */ jsx(Grid, { item: true, xs: 12, children: /* @__PURE__ */ jsxs(Alert, { severity: "error", children: [
|
|
61
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body1", children: isMetricsModuleError ? "HTTP metrics are unavailable. Check the metrics module configuration." : "Failed to load HTTP metrics." }),
|
|
62
|
+
/* @__PURE__ */ jsx(Typography, { variant: "body2", children: error }),
|
|
63
|
+
!isMetricsModuleError && /* @__PURE__ */ jsx(
|
|
64
|
+
Button,
|
|
65
|
+
{
|
|
66
|
+
onClick: () => fetchMetrics(true),
|
|
67
|
+
color: "inherit",
|
|
68
|
+
size: "small",
|
|
69
|
+
children: "Retry"
|
|
70
|
+
}
|
|
71
|
+
)
|
|
72
|
+
] }) });
|
|
73
|
+
}
|
|
74
|
+
const throughputData = httpMetrics?.networkThroughput || {};
|
|
75
|
+
const latencyData = httpMetrics?.networkLatency || {};
|
|
76
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
77
|
+
/* @__PURE__ */ jsx(Grid, { item: true, xs: 12, md: 6, children: /* @__PURE__ */ jsxs(Card, { children: [
|
|
78
|
+
/* @__PURE__ */ jsx(CardHeader, { title: "Network Throughput" }),
|
|
79
|
+
/* @__PURE__ */ jsx(Divider, {}),
|
|
80
|
+
/* @__PURE__ */ jsx(CardContent, { children: /* @__PURE__ */ jsx(
|
|
81
|
+
MetricGraphByComponent,
|
|
82
|
+
{
|
|
83
|
+
usageData: throughputData,
|
|
84
|
+
usageType: "networkThroughput",
|
|
85
|
+
timeRange: filters.timeRange,
|
|
86
|
+
customStartTime: filters.customStartTime,
|
|
87
|
+
customEndTime: filters.customEndTime
|
|
88
|
+
}
|
|
89
|
+
) })
|
|
90
|
+
] }) }),
|
|
91
|
+
/* @__PURE__ */ jsx(Grid, { item: true, xs: 12, md: 6, children: /* @__PURE__ */ jsxs(Card, { children: [
|
|
92
|
+
/* @__PURE__ */ jsx(CardHeader, { title: "Network Latency" }),
|
|
93
|
+
/* @__PURE__ */ jsx(Divider, {}),
|
|
94
|
+
/* @__PURE__ */ jsx(CardContent, { children: /* @__PURE__ */ jsx(
|
|
95
|
+
MetricGraphByComponent,
|
|
96
|
+
{
|
|
97
|
+
usageData: latencyData,
|
|
98
|
+
usageType: "networkLatency",
|
|
99
|
+
timeRange: filters.timeRange,
|
|
100
|
+
customStartTime: filters.customStartTime,
|
|
101
|
+
customEndTime: filters.customEndTime
|
|
102
|
+
}
|
|
103
|
+
) })
|
|
104
|
+
] }) })
|
|
105
|
+
] });
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
export { HTTPMetricsSection };
|
|
109
|
+
//# sourceMappingURL=HTTPMetricsSection.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HTTPMetricsSection.esm.js","sources":["../../../src/components/Metrics/HTTPMetricsSection.tsx"],"sourcesContent":["import { useEffect, useRef } from 'react';\nimport {\n Button,\n Card,\n CardContent,\n CardHeader,\n Divider,\n Grid,\n Typography,\n} from '@material-ui/core';\nimport { Alert } from '@material-ui/lab';\nimport { MetricGraphByComponent } from './MetricGraphByComponent';\nimport {\n Filters,\n HttpMetrics,\n NetworkLatencyMetrics,\n NetworkThroughputMetrics,\n} from '../../types';\nimport { Entity } from '@backstage/catalog-model';\nimport { useMetrics, useDataPlaneNetPolProvider } from '../../hooks';\n\ntype HTTPMetricsSectionProps = {\n filters: Filters;\n entity: Entity;\n namespaceName: string;\n project: string;\n};\n\nexport const HTTPMetricsSection = ({\n filters,\n entity,\n namespaceName,\n project,\n}: HTTPMetricsSectionProps) => {\n const { networkPolicyProvider, loading: netPolLoading } =\n useDataPlaneNetPolProvider(\n namespaceName,\n filters.environment?.dataPlaneRef,\n );\n const httpEnabled = networkPolicyProvider === 'cilium';\n const { metrics, error, fetchMetrics } = useMetrics(\n filters,\n entity,\n namespaceName,\n project,\n 'http',\n );\n const httpMetrics = metrics as HttpMetrics;\n\n const previousFiltersRef = useRef({\n environment: undefined as string | undefined,\n timeRange: undefined as string | undefined,\n });\n\n useEffect(() => {\n if (!httpEnabled) {\n return;\n }\n\n const currentFilters = {\n environment: filters.environment?.name,\n timeRange: filters.timeRange,\n };\n\n const filtersChanged =\n JSON.stringify(previousFiltersRef.current) !==\n JSON.stringify(currentFilters);\n\n if (filters.environment && filters.timeRange && filtersChanged) {\n fetchMetrics(true);\n }\n\n previousFiltersRef.current = currentFilters;\n }, [httpEnabled, filters.environment, filters.timeRange, fetchMetrics]);\n\n if (netPolLoading || !httpEnabled) {\n return null;\n }\n\n if (error) {\n const isMetricsModuleError = error.toLowerCase().includes('metrics module');\n\n return (\n <Grid item xs={12}>\n <Alert severity=\"error\">\n <Typography variant=\"body1\">\n {isMetricsModuleError\n ? 'HTTP metrics are unavailable. Check the metrics module configuration.'\n : 'Failed to load HTTP metrics.'}\n </Typography>\n <Typography variant=\"body2\">{error}</Typography>\n {!isMetricsModuleError && (\n <Button\n onClick={() => fetchMetrics(true)}\n color=\"inherit\"\n size=\"small\"\n >\n Retry\n </Button>\n )}\n </Alert>\n </Grid>\n );\n }\n\n const throughputData =\n httpMetrics?.networkThroughput || ({} as NetworkThroughputMetrics);\n const latencyData =\n httpMetrics?.networkLatency || ({} as NetworkLatencyMetrics);\n\n return (\n <>\n <Grid item xs={12} md={6}>\n <Card>\n <CardHeader title=\"Network Throughput\" />\n <Divider />\n <CardContent>\n <MetricGraphByComponent\n usageData={throughputData}\n usageType=\"networkThroughput\"\n timeRange={filters.timeRange}\n customStartTime={filters.customStartTime}\n customEndTime={filters.customEndTime}\n />\n </CardContent>\n </Card>\n </Grid>\n <Grid item xs={12} md={6}>\n <Card>\n <CardHeader title=\"Network Latency\" />\n <Divider />\n <CardContent>\n <MetricGraphByComponent\n usageData={latencyData}\n usageType=\"networkLatency\"\n timeRange={filters.timeRange}\n customStartTime={filters.customStartTime}\n customEndTime={filters.customEndTime}\n />\n </CardContent>\n </Card>\n </Grid>\n </>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AA4BO,MAAM,qBAAqB,CAAC;AAAA,EACjC,OAAA;AAAA,EACA,MAAA;AAAA,EACA,aAAA;AAAA,EACA;AACF,CAAA,KAA+B;AAC7B,EAAA,MAAM,EAAE,qBAAA,EAAuB,OAAA,EAAS,aAAA,EAAc,GACpD,0BAAA;AAAA,IACE,aAAA;AAAA,IACA,QAAQ,WAAA,EAAa;AAAA,GACvB;AACF,EAAA,MAAM,cAAc,qBAAA,KAA0B,QAAA;AAC9C,EAAA,MAAM,EAAE,OAAA,EAAS,KAAA,EAAO,YAAA,EAAa,GAAI,UAAA;AAAA,IACvC,OAAA;AAAA,IACA,MAAA;AAAA,IACA,aAAA;AAAA,IACA,OAAA;AAAA,IACA;AAAA,GACF;AACA,EAAA,MAAM,WAAA,GAAc,OAAA;AAEpB,EAAA,MAAM,qBAAqB,MAAA,CAAO;AAAA,IAChC,WAAA,EAAa,MAAA;AAAA,IACb,SAAA,EAAW;AAAA,GACZ,CAAA;AAED,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,CAAC,WAAA,EAAa;AAChB,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,cAAA,GAAiB;AAAA,MACrB,WAAA,EAAa,QAAQ,WAAA,EAAa,IAAA;AAAA,MAClC,WAAW,OAAA,CAAQ;AAAA,KACrB;AAEA,IAAA,MAAM,cAAA,GACJ,KAAK,SAAA,CAAU,kBAAA,CAAmB,OAAO,CAAA,KACzC,IAAA,CAAK,UAAU,cAAc,CAAA;AAE/B,IAAA,IAAI,OAAA,CAAQ,WAAA,IAAe,OAAA,CAAQ,SAAA,IAAa,cAAA,EAAgB;AAC9D,MAAA,YAAA,CAAa,IAAI,CAAA;AAAA,IACnB;AAEA,IAAA,kBAAA,CAAmB,OAAA,GAAU,cAAA;AAAA,EAC/B,CAAA,EAAG,CAAC,WAAA,EAAa,OAAA,CAAQ,aAAa,OAAA,CAAQ,SAAA,EAAW,YAAY,CAAC,CAAA;AAEtE,EAAA,IAAI,aAAA,IAAiB,CAAC,WAAA,EAAa;AACjC,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,IAAI,KAAA,EAAO;AACT,IAAA,MAAM,oBAAA,GAAuB,KAAA,CAAM,WAAA,EAAY,CAAE,SAAS,gBAAgB,CAAA;AAE1E,IAAA,uBACE,GAAA,CAAC,QAAK,IAAA,EAAI,IAAA,EAAC,IAAI,EAAA,EACb,QAAA,kBAAA,IAAA,CAAC,KAAA,EAAA,EAAM,QAAA,EAAS,OAAA,EACd,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,UAAA,EAAA,EAAW,OAAA,EAAQ,OAAA,EACjB,QAAA,EAAA,oBAAA,GACG,0EACA,8BAAA,EACN,CAAA;AAAA,sBACA,GAAA,CAAC,UAAA,EAAA,EAAW,OAAA,EAAQ,OAAA,EAAS,QAAA,EAAA,KAAA,EAAM,CAAA;AAAA,MAClC,CAAC,oBAAA,oBACA,GAAA;AAAA,QAAC,MAAA;AAAA,QAAA;AAAA,UACC,OAAA,EAAS,MAAM,YAAA,CAAa,IAAI,CAAA;AAAA,UAChC,KAAA,EAAM,SAAA;AAAA,UACN,IAAA,EAAK,OAAA;AAAA,UACN,QAAA,EAAA;AAAA;AAAA;AAED,KAAA,EAEJ,CAAA,EACF,CAAA;AAAA,EAEJ;AAEA,EAAA,MAAM,cAAA,GACJ,WAAA,EAAa,iBAAA,IAAsB,EAAC;AACtC,EAAA,MAAM,WAAA,GACJ,WAAA,EAAa,cAAA,IAAmB,EAAC;AAEnC,EAAA,uBACE,IAAA,CAAA,QAAA,EAAA,EACE,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,IAAA,EAAA,EAAK,MAAI,IAAA,EAAC,EAAA,EAAI,IAAI,EAAA,EAAI,CAAA,EACrB,+BAAC,IAAA,EAAA,EACC,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,UAAA,EAAA,EAAW,OAAM,oBAAA,EAAqB,CAAA;AAAA,0BACtC,OAAA,EAAA,EAAQ,CAAA;AAAA,0BACR,WAAA,EAAA,EACC,QAAA,kBAAA,GAAA;AAAA,QAAC,sBAAA;AAAA,QAAA;AAAA,UACC,SAAA,EAAW,cAAA;AAAA,UACX,SAAA,EAAU,mBAAA;AAAA,UACV,WAAW,OAAA,CAAQ,SAAA;AAAA,UACnB,iBAAiB,OAAA,CAAQ,eAAA;AAAA,UACzB,eAAe,OAAA,CAAQ;AAAA;AAAA,OACzB,EACF;AAAA,KAAA,EACF,CAAA,EACF,CAAA;AAAA,oBACA,GAAA,CAAC,QAAK,IAAA,EAAI,IAAA,EAAC,IAAI,EAAA,EAAI,EAAA,EAAI,CAAA,EACrB,QAAA,kBAAA,IAAA,CAAC,IAAA,EAAA,EACC,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,UAAA,EAAA,EAAW,OAAM,iBAAA,EAAkB,CAAA;AAAA,0BACnC,OAAA,EAAA,EAAQ,CAAA;AAAA,0BACR,WAAA,EAAA,EACC,QAAA,kBAAA,GAAA;AAAA,QAAC,sBAAA;AAAA,QAAA;AAAA,UACC,SAAA,EAAW,WAAA;AAAA,UACX,SAAA,EAAU,gBAAA;AAAA,UACV,WAAW,OAAA,CAAQ,SAAA;AAAA,UACnB,iBAAiB,OAAA,CAAQ,eAAA;AAAA,UACzB,eAAe,OAAA,CAAQ;AAAA;AAAA,OACzB,EACF;AAAA,KAAA,EACF,CAAA,EACF;AAAA,GAAA,EACF,CAAA;AAEJ;;;;"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { useState, useMemo } from 'react';
|
|
3
|
+
import { LineChart, CartesianGrid, XAxis, YAxis, Tooltip, Legend, Line } from 'recharts';
|
|
4
|
+
import { transformMetricsData, calculateTimeDomain, getMetricConfigs, formatAxisTime, formatMetricValue, formatTooltipTime, getLineOpacity, formatMetricName } from './utils.esm.js';
|
|
5
|
+
import { useMetricGraphStyles } from './styles.esm.js';
|
|
6
|
+
import { ChartTooltip } from './ChartTooltip.esm.js';
|
|
7
|
+
|
|
8
|
+
const MetricGraphByComponent = ({
|
|
9
|
+
usageData,
|
|
10
|
+
usageType,
|
|
11
|
+
timeRange,
|
|
12
|
+
customStartTime,
|
|
13
|
+
customEndTime
|
|
14
|
+
}) => {
|
|
15
|
+
const classes = useMetricGraphStyles();
|
|
16
|
+
const [hoveringDataKey, setHoveringDataKey] = useState();
|
|
17
|
+
const transformedData = useMemo(
|
|
18
|
+
() => transformMetricsData(usageData),
|
|
19
|
+
[usageData]
|
|
20
|
+
);
|
|
21
|
+
const { ticks, daysRange, domain } = useMemo(
|
|
22
|
+
() => calculateTimeDomain(transformedData, timeRange, 5, {
|
|
23
|
+
startTime: customStartTime,
|
|
24
|
+
endTime: customEndTime
|
|
25
|
+
}),
|
|
26
|
+
[transformedData, timeRange, customStartTime, customEndTime]
|
|
27
|
+
);
|
|
28
|
+
const metrics = useMemo(() => getMetricConfigs(usageType), [usageType]);
|
|
29
|
+
const handleMouseEnter = (payload) => setHoveringDataKey(payload.dataKey);
|
|
30
|
+
const handleMouseLeave = () => setHoveringDataKey(void 0);
|
|
31
|
+
return /* @__PURE__ */ jsxs("div", { className: classes.chartContainer, children: [
|
|
32
|
+
transformedData.length === 0 && /* @__PURE__ */ jsx("div", { className: classes.emptyOverlay, children: "No data available" }),
|
|
33
|
+
/* @__PURE__ */ jsxs(
|
|
34
|
+
LineChart,
|
|
35
|
+
{
|
|
36
|
+
className: classes.lineChart,
|
|
37
|
+
responsive: true,
|
|
38
|
+
data: transformedData,
|
|
39
|
+
children: [
|
|
40
|
+
/* @__PURE__ */ jsx(CartesianGrid, { strokeDasharray: "3 3" }),
|
|
41
|
+
/* @__PURE__ */ jsx(
|
|
42
|
+
XAxis,
|
|
43
|
+
{
|
|
44
|
+
dataKey: "timestamp",
|
|
45
|
+
type: "number",
|
|
46
|
+
domain,
|
|
47
|
+
tickFormatter: (ts) => formatAxisTime(ts, daysRange),
|
|
48
|
+
ticks,
|
|
49
|
+
tick: { fontSize: 12 }
|
|
50
|
+
}
|
|
51
|
+
),
|
|
52
|
+
/* @__PURE__ */ jsx(
|
|
53
|
+
YAxis,
|
|
54
|
+
{
|
|
55
|
+
width: "auto",
|
|
56
|
+
tickFormatter: (v) => formatMetricValue(v, usageType)
|
|
57
|
+
}
|
|
58
|
+
),
|
|
59
|
+
/* @__PURE__ */ jsx(
|
|
60
|
+
Tooltip,
|
|
61
|
+
{
|
|
62
|
+
content: /* @__PURE__ */ jsx(
|
|
63
|
+
ChartTooltip,
|
|
64
|
+
{
|
|
65
|
+
labelFormatter: formatTooltipTime,
|
|
66
|
+
formatter: (value) => formatMetricValue(value, usageType)
|
|
67
|
+
}
|
|
68
|
+
)
|
|
69
|
+
}
|
|
70
|
+
),
|
|
71
|
+
/* @__PURE__ */ jsx(
|
|
72
|
+
Legend,
|
|
73
|
+
{
|
|
74
|
+
onMouseEnter: handleMouseEnter,
|
|
75
|
+
onMouseLeave: handleMouseLeave
|
|
76
|
+
}
|
|
77
|
+
),
|
|
78
|
+
Object.entries(metrics).map(([, { key, color }]) => /* @__PURE__ */ jsx(
|
|
79
|
+
Line,
|
|
80
|
+
{
|
|
81
|
+
type: "monotone",
|
|
82
|
+
dataKey: key,
|
|
83
|
+
name: formatMetricName(key),
|
|
84
|
+
strokeOpacity: getLineOpacity(key, hoveringDataKey),
|
|
85
|
+
stroke: color,
|
|
86
|
+
dot: false,
|
|
87
|
+
activeDot: { r: 4 },
|
|
88
|
+
connectNulls: false
|
|
89
|
+
},
|
|
90
|
+
key
|
|
91
|
+
))
|
|
92
|
+
]
|
|
93
|
+
}
|
|
94
|
+
)
|
|
95
|
+
] });
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
export { MetricGraphByComponent };
|
|
99
|
+
//# sourceMappingURL=MetricGraphByComponent.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MetricGraphByComponent.esm.js","sources":["../../../src/components/Metrics/MetricGraphByComponent.tsx"],"sourcesContent":["import { useState, useMemo } from 'react';\nimport {\n LineChart,\n Line,\n XAxis,\n YAxis,\n CartesianGrid,\n Tooltip,\n Legend,\n LegendPayload,\n} from 'recharts';\nimport { DataKey } from 'recharts/types/util/types';\nimport {\n CpuUsageMetrics,\n MemoryUsageMetrics,\n NetworkLatencyMetrics,\n NetworkThroughputMetrics,\n} from '../../types';\nimport {\n formatAxisTime,\n formatTooltipTime,\n formatMetricValue,\n calculateTimeDomain,\n transformMetricsData,\n getMetricConfigs,\n getLineOpacity,\n formatMetricName,\n} from './utils';\nimport { useMetricGraphStyles } from './styles';\nimport { ChartTooltip } from './ChartTooltip';\n\nexport const MetricGraphByComponent = ({\n usageData,\n usageType,\n timeRange,\n customStartTime,\n customEndTime,\n}: {\n usageData:\n | CpuUsageMetrics\n | MemoryUsageMetrics\n | NetworkThroughputMetrics\n | NetworkLatencyMetrics;\n usageType: 'cpu' | 'memory' | 'networkThroughput' | 'networkLatency';\n timeRange?: string;\n customStartTime?: string;\n customEndTime?: string;\n}) => {\n const classes = useMetricGraphStyles();\n const [hoveringDataKey, setHoveringDataKey] = useState<\n DataKey<any> | undefined\n >();\n\n const transformedData = useMemo(\n () => transformMetricsData(usageData),\n [usageData],\n );\n\n const { ticks, daysRange, domain } = useMemo(\n () =>\n calculateTimeDomain(transformedData, timeRange, 5, {\n startTime: customStartTime,\n endTime: customEndTime,\n }),\n [transformedData, timeRange, customStartTime, customEndTime],\n );\n\n const metrics = useMemo(() => getMetricConfigs(usageType), [usageType]);\n\n const handleMouseEnter = (payload: LegendPayload) =>\n setHoveringDataKey(payload.dataKey);\n\n const handleMouseLeave = () => setHoveringDataKey(undefined);\n\n return (\n <div className={classes.chartContainer}>\n {transformedData.length === 0 && (\n <div className={classes.emptyOverlay}>No data available</div>\n )}\n <LineChart\n className={classes.lineChart}\n responsive\n data={transformedData}\n >\n <CartesianGrid strokeDasharray=\"3 3\" />\n <XAxis\n dataKey=\"timestamp\"\n type=\"number\"\n domain={domain}\n tickFormatter={ts => formatAxisTime(ts, daysRange)}\n ticks={ticks}\n tick={{ fontSize: 12 }}\n />\n <YAxis\n width=\"auto\"\n tickFormatter={v => formatMetricValue(v, usageType)}\n />\n <Tooltip\n content={\n <ChartTooltip\n labelFormatter={formatTooltipTime}\n formatter={(value: number) => formatMetricValue(value, usageType)}\n />\n }\n />\n <Legend\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n />\n {Object.entries(metrics).map(([, { key, color }]) => (\n <Line\n key={key}\n type=\"monotone\"\n dataKey={key}\n name={formatMetricName(key)}\n strokeOpacity={getLineOpacity(key, hoveringDataKey)}\n stroke={color}\n dot={false}\n activeDot={{ r: 4 }}\n connectNulls={false}\n />\n ))}\n </LineChart>\n </div>\n );\n};\n"],"names":[],"mappings":";;;;;;;AA+BO,MAAM,yBAAyB,CAAC;AAAA,EACrC,SAAA;AAAA,EACA,SAAA;AAAA,EACA,SAAA;AAAA,EACA,eAAA;AAAA,EACA;AACF,CAAA,KAUM;AACJ,EAAA,MAAM,UAAU,oBAAA,EAAqB;AACrC,EAAA,MAAM,CAAC,eAAA,EAAiB,kBAAkB,CAAA,GAAI,QAAA,EAE5C;AAEF,EAAA,MAAM,eAAA,GAAkB,OAAA;AAAA,IACtB,MAAM,qBAAqB,SAAS,CAAA;AAAA,IACpC,CAAC,SAAS;AAAA,GACZ;AAEA,EAAA,MAAM,EAAE,KAAA,EAAO,SAAA,EAAW,MAAA,EAAO,GAAI,OAAA;AAAA,IACnC,MACE,mBAAA,CAAoB,eAAA,EAAiB,SAAA,EAAW,CAAA,EAAG;AAAA,MACjD,SAAA,EAAW,eAAA;AAAA,MACX,OAAA,EAAS;AAAA,KACV,CAAA;AAAA,IACH,CAAC,eAAA,EAAiB,SAAA,EAAW,eAAA,EAAiB,aAAa;AAAA,GAC7D;AAEA,EAAA,MAAM,OAAA,GAAU,QAAQ,MAAM,gBAAA,CAAiB,SAAS,CAAA,EAAG,CAAC,SAAS,CAAC,CAAA;AAEtE,EAAA,MAAM,gBAAA,GAAmB,CAAC,OAAA,KACxB,kBAAA,CAAmB,QAAQ,OAAO,CAAA;AAEpC,EAAA,MAAM,gBAAA,GAAmB,MAAM,kBAAA,CAAmB,MAAS,CAAA;AAE3D,EAAA,uBACE,IAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,OAAA,CAAQ,cAAA,EACrB,QAAA,EAAA;AAAA,IAAA,eAAA,CAAgB,WAAW,CAAA,oBAC1B,GAAA,CAAC,SAAI,SAAA,EAAW,OAAA,CAAQ,cAAc,QAAA,EAAA,mBAAA,EAAiB,CAAA;AAAA,oBAEzD,IAAA;AAAA,MAAC,SAAA;AAAA,MAAA;AAAA,QACC,WAAW,OAAA,CAAQ,SAAA;AAAA,QACnB,UAAA,EAAU,IAAA;AAAA,QACV,IAAA,EAAM,eAAA;AAAA,QAEN,QAAA,EAAA;AAAA,0BAAA,GAAA,CAAC,aAAA,EAAA,EAAc,iBAAgB,KAAA,EAAM,CAAA;AAAA,0BACrC,GAAA;AAAA,YAAC,KAAA;AAAA,YAAA;AAAA,cACC,OAAA,EAAQ,WAAA;AAAA,cACR,IAAA,EAAK,QAAA;AAAA,cACL,MAAA;AAAA,cACA,aAAA,EAAe,CAAA,EAAA,KAAM,cAAA,CAAe,EAAA,EAAI,SAAS,CAAA;AAAA,cACjD,KAAA;AAAA,cACA,IAAA,EAAM,EAAE,QAAA,EAAU,EAAA;AAAG;AAAA,WACvB;AAAA,0BACA,GAAA;AAAA,YAAC,KAAA;AAAA,YAAA;AAAA,cACC,KAAA,EAAM,MAAA;AAAA,cACN,aAAA,EAAe,CAAA,CAAA,KAAK,iBAAA,CAAkB,CAAA,EAAG,SAAS;AAAA;AAAA,WACpD;AAAA,0BACA,GAAA;AAAA,YAAC,OAAA;AAAA,YAAA;AAAA,cACC,OAAA,kBACE,GAAA;AAAA,gBAAC,YAAA;AAAA,gBAAA;AAAA,kBACC,cAAA,EAAgB,iBAAA;AAAA,kBAChB,SAAA,EAAW,CAAC,KAAA,KAAkB,iBAAA,CAAkB,OAAO,SAAS;AAAA;AAAA;AAClE;AAAA,WAEJ;AAAA,0BACA,GAAA;AAAA,YAAC,MAAA;AAAA,YAAA;AAAA,cACC,YAAA,EAAc,gBAAA;AAAA,cACd,YAAA,EAAc;AAAA;AAAA,WAChB;AAAA,UACC,MAAA,CAAO,OAAA,CAAQ,OAAO,CAAA,CAAE,GAAA,CAAI,CAAC,GAAG,EAAE,GAAA,EAAK,KAAA,EAAO,CAAA,qBAC7C,GAAA;AAAA,YAAC,IAAA;AAAA,YAAA;AAAA,cAEC,IAAA,EAAK,UAAA;AAAA,cACL,OAAA,EAAS,GAAA;AAAA,cACT,IAAA,EAAM,iBAAiB,GAAG,CAAA;AAAA,cAC1B,aAAA,EAAe,cAAA,CAAe,GAAA,EAAK,eAAe,CAAA;AAAA,cAClD,MAAA,EAAQ,KAAA;AAAA,cACR,GAAA,EAAK,KAAA;AAAA,cACL,SAAA,EAAW,EAAE,CAAA,EAAG,CAAA,EAAE;AAAA,cAClB,YAAA,EAAc;AAAA,aAAA;AAAA,YART;AAAA,WAUR;AAAA;AAAA;AAAA;AACH,GAAA,EACF,CAAA;AAEJ;;;;"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { Box, Typography, Button } from '@material-ui/core';
|
|
3
|
+
import Refresh from '@material-ui/icons/Refresh';
|
|
4
|
+
import { useMetricsActionsStyles } from './styles.esm.js';
|
|
5
|
+
|
|
6
|
+
const MetricsActions = ({
|
|
7
|
+
disabled,
|
|
8
|
+
onRefresh
|
|
9
|
+
}) => {
|
|
10
|
+
const classes = useMetricsActionsStyles();
|
|
11
|
+
return /* @__PURE__ */ jsxs(Box, { className: classes.statsContainer, children: [
|
|
12
|
+
/* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Typography, { variant: "body2", color: "textSecondary", children: [
|
|
13
|
+
"Last updated at: ",
|
|
14
|
+
(/* @__PURE__ */ new Date()).toLocaleString()
|
|
15
|
+
] }) }),
|
|
16
|
+
/* @__PURE__ */ jsx(Box, { className: classes.actionsContainer, children: /* @__PURE__ */ jsx(
|
|
17
|
+
Button,
|
|
18
|
+
{
|
|
19
|
+
variant: "outlined",
|
|
20
|
+
startIcon: /* @__PURE__ */ jsx(Refresh, {}),
|
|
21
|
+
onClick: onRefresh,
|
|
22
|
+
disabled,
|
|
23
|
+
children: "Refresh"
|
|
24
|
+
}
|
|
25
|
+
) })
|
|
26
|
+
] });
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export { MetricsActions };
|
|
30
|
+
//# sourceMappingURL=MetricsActions.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MetricsActions.esm.js","sources":["../../../src/components/Metrics/MetricsActions.tsx"],"sourcesContent":["import { Box, Typography, Button } from '@material-ui/core';\nimport Refresh from '@material-ui/icons/Refresh';\nimport { useMetricsActionsStyles } from './styles';\n\ninterface MetricsActionsProps {\n disabled: boolean;\n onRefresh: () => void;\n}\n\nexport const MetricsActions = ({\n disabled,\n onRefresh,\n}: MetricsActionsProps) => {\n const classes = useMetricsActionsStyles();\n return (\n <Box className={classes.statsContainer}>\n <Box>\n <Typography variant=\"body2\" color=\"textSecondary\">\n Last updated at: {new Date().toLocaleString()}\n </Typography>\n </Box>\n <Box className={classes.actionsContainer}>\n <Button\n variant=\"outlined\"\n startIcon={<Refresh />}\n onClick={onRefresh}\n disabled={disabled}\n >\n Refresh\n </Button>\n {/* TODO: Add Auto Refresh Button */}\n </Box>\n </Box>\n );\n};\n"],"names":[],"mappings":";;;;;AASO,MAAM,iBAAiB,CAAC;AAAA,EAC7B,QAAA;AAAA,EACA;AACF,CAAA,KAA2B;AACzB,EAAA,MAAM,UAAU,uBAAA,EAAwB;AACxC,EAAA,uBACE,IAAA,CAAC,GAAA,EAAA,EAAI,SAAA,EAAW,OAAA,CAAQ,cAAA,EACtB,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,OACC,QAAA,kBAAA,IAAA,CAAC,UAAA,EAAA,EAAW,OAAA,EAAQ,OAAA,EAAQ,OAAM,eAAA,EAAgB,QAAA,EAAA;AAAA,MAAA,mBAAA;AAAA,MAAA,iBAC9B,IAAI,IAAA,EAAK,EAAE,cAAA;AAAe,KAAA,EAC9C,CAAA,EACF,CAAA;AAAA,oBACA,GAAA,CAAC,GAAA,EAAA,EAAI,SAAA,EAAW,OAAA,CAAQ,gBAAA,EACtB,QAAA,kBAAA,GAAA;AAAA,MAAC,MAAA;AAAA,MAAA;AAAA,QACC,OAAA,EAAQ,UAAA;AAAA,QACR,SAAA,sBAAY,OAAA,EAAA,EAAQ,CAAA;AAAA,QACpB,OAAA,EAAS,SAAA;AAAA,QACT,QAAA;AAAA,QACD,QAAA,EAAA;AAAA;AAAA,KAED,EAEF;AAAA,GAAA,EACF,CAAA;AAEJ;;;;"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { Grid, FormControl, InputLabel, Select, MenuItem } from '@material-ui/core';
|
|
3
|
+
import { TimeRangeFilter } from '../TimeRangeFilter/TimeRangeFilter.esm.js';
|
|
4
|
+
|
|
5
|
+
const MetricsFilters = ({
|
|
6
|
+
filters,
|
|
7
|
+
onFiltersChange,
|
|
8
|
+
environments,
|
|
9
|
+
disabled = false
|
|
10
|
+
}) => {
|
|
11
|
+
const handleEnvironmentChange = (event) => {
|
|
12
|
+
const selectedEnvironment = environments.find(
|
|
13
|
+
(env) => env.uid === event.target.value
|
|
14
|
+
);
|
|
15
|
+
if (selectedEnvironment) {
|
|
16
|
+
onFiltersChange({ environment: selectedEnvironment });
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
return /* @__PURE__ */ jsxs(Grid, { container: true, spacing: 3, children: [
|
|
20
|
+
/* @__PURE__ */ jsx(Grid, { item: true, xs: 12, md: 3 }),
|
|
21
|
+
/* @__PURE__ */ jsx(Grid, { item: true, xs: 12, md: 3 }),
|
|
22
|
+
/* @__PURE__ */ jsx(Grid, { item: true, xs: 12, md: 3, children: /* @__PURE__ */ jsxs(FormControl, { fullWidth: true, disabled, variant: "outlined", children: [
|
|
23
|
+
/* @__PURE__ */ jsx(InputLabel, { id: "environment-label", children: "Environment" }),
|
|
24
|
+
/* @__PURE__ */ jsx(
|
|
25
|
+
Select,
|
|
26
|
+
{
|
|
27
|
+
value: filters.environment?.uid || "",
|
|
28
|
+
onChange: handleEnvironmentChange,
|
|
29
|
+
labelId: "environment-label",
|
|
30
|
+
label: "Environment",
|
|
31
|
+
children: environments.map((environment) => /* @__PURE__ */ jsx(MenuItem, { value: environment.uid, children: environment.displayName || environment.name }, environment.uid))
|
|
32
|
+
}
|
|
33
|
+
)
|
|
34
|
+
] }) }),
|
|
35
|
+
/* @__PURE__ */ jsx(Grid, { item: true, xs: 12, md: 3, children: /* @__PURE__ */ jsx(
|
|
36
|
+
TimeRangeFilter,
|
|
37
|
+
{
|
|
38
|
+
value: filters.timeRange,
|
|
39
|
+
customStartTime: filters.customStartTime,
|
|
40
|
+
customEndTime: filters.customEndTime,
|
|
41
|
+
onChange: onFiltersChange,
|
|
42
|
+
disabled
|
|
43
|
+
}
|
|
44
|
+
) })
|
|
45
|
+
] });
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export { MetricsFilters };
|
|
49
|
+
//# sourceMappingURL=MetricsFilters.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MetricsFilters.esm.js","sources":["../../../src/components/Metrics/MetricsFilters.tsx"],"sourcesContent":["import {\n FormControl,\n InputLabel,\n Select,\n MenuItem,\n Grid,\n} from '@material-ui/core';\nimport { Filters, Environment } from '../../types';\nimport { TimeRangeFilter } from '../TimeRangeFilter';\n\ninterface MetricsFiltersProps {\n filters: Filters;\n onFiltersChange: (filters: Partial<Filters>) => void;\n environments: Environment[];\n disabled?: boolean;\n}\n\nexport const MetricsFilters = ({\n filters,\n onFiltersChange,\n environments,\n disabled = false,\n}: MetricsFiltersProps) => {\n const handleEnvironmentChange = (\n event: React.ChangeEvent<{ value: unknown }>,\n ) => {\n const selectedEnvironment = environments.find(\n env => env.uid === (event.target.value as string),\n );\n if (selectedEnvironment) {\n onFiltersChange({ environment: selectedEnvironment });\n }\n };\n\n return (\n <Grid container spacing={3}>\n <Grid item xs={12} md={3}>\n {/* TODO: Add Filters for Metrics */}\n </Grid>\n\n <Grid item xs={12} md={3}>\n {/* TODO: Add Filters for Metrics */}\n </Grid>\n\n <Grid item xs={12} md={3}>\n <FormControl fullWidth disabled={disabled} variant=\"outlined\">\n <InputLabel id=\"environment-label\">Environment</InputLabel>\n <Select\n value={filters.environment?.uid || ''}\n onChange={handleEnvironmentChange}\n labelId=\"environment-label\"\n label=\"Environment\"\n >\n {environments.map((environment: Environment) => (\n <MenuItem key={environment.uid} value={environment.uid}>\n {environment.displayName || environment.name}\n </MenuItem>\n ))}\n </Select>\n </FormControl>\n </Grid>\n\n <Grid item xs={12} md={3}>\n <TimeRangeFilter\n value={filters.timeRange}\n customStartTime={filters.customStartTime}\n customEndTime={filters.customEndTime}\n onChange={onFiltersChange}\n disabled={disabled}\n />\n </Grid>\n </Grid>\n );\n};\n"],"names":[],"mappings":";;;;AAiBO,MAAM,iBAAiB,CAAC;AAAA,EAC7B,OAAA;AAAA,EACA,eAAA;AAAA,EACA,YAAA;AAAA,EACA,QAAA,GAAW;AACb,CAAA,KAA2B;AACzB,EAAA,MAAM,uBAAA,GAA0B,CAC9B,KAAA,KACG;AACH,IAAA,MAAM,sBAAsB,YAAA,CAAa,IAAA;AAAA,MACvC,CAAA,GAAA,KAAO,GAAA,CAAI,GAAA,KAAS,KAAA,CAAM,MAAA,CAAO;AAAA,KACnC;AACA,IAAA,IAAI,mBAAA,EAAqB;AACvB,MAAA,eAAA,CAAgB,EAAE,WAAA,EAAa,mBAAA,EAAqB,CAAA;AAAA,IACtD;AAAA,EACF,CAAA;AAEA,EAAA,uBACE,IAAA,CAAC,IAAA,EAAA,EAAK,SAAA,EAAS,IAAA,EAAC,SAAS,CAAA,EACvB,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,QAAK,IAAA,EAAI,IAAA,EAAC,EAAA,EAAI,EAAA,EAAI,IAAI,CAAA,EAEvB,CAAA;AAAA,wBAEC,IAAA,EAAA,EAAK,IAAA,EAAI,MAAC,EAAA,EAAI,EAAA,EAAI,IAAI,CAAA,EAEvB,CAAA;AAAA,oBAEA,GAAA,CAAC,IAAA,EAAA,EAAK,IAAA,EAAI,IAAA,EAAC,IAAI,EAAA,EAAI,EAAA,EAAI,CAAA,EACrB,QAAA,kBAAA,IAAA,CAAC,WAAA,EAAA,EAAY,SAAA,EAAS,IAAA,EAAC,QAAA,EAAoB,SAAQ,UAAA,EACjD,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,UAAA,EAAA,EAAW,EAAA,EAAG,mBAAA,EAAoB,QAAA,EAAA,aAAA,EAAW,CAAA;AAAA,sBAC9C,GAAA;AAAA,QAAC,MAAA;AAAA,QAAA;AAAA,UACC,KAAA,EAAO,OAAA,CAAQ,WAAA,EAAa,GAAA,IAAO,EAAA;AAAA,UACnC,QAAA,EAAU,uBAAA;AAAA,UACV,OAAA,EAAQ,mBAAA;AAAA,UACR,KAAA,EAAM,aAAA;AAAA,UAEL,QAAA,EAAA,YAAA,CAAa,GAAA,CAAI,CAAC,WAAA,yBAChB,QAAA,EAAA,EAA+B,KAAA,EAAO,WAAA,CAAY,GAAA,EAChD,sBAAY,WAAA,IAAe,WAAA,CAAY,IAAA,EAAA,EAD3B,WAAA,CAAY,GAE3B,CACD;AAAA;AAAA;AACH,KAAA,EACF,CAAA,EACF,CAAA;AAAA,wBAEC,IAAA,EAAA,EAAK,IAAA,EAAI,MAAC,EAAA,EAAI,EAAA,EAAI,IAAI,CAAA,EACrB,QAAA,kBAAA,GAAA;AAAA,MAAC,eAAA;AAAA,MAAA;AAAA,QACC,OAAO,OAAA,CAAQ,SAAA;AAAA,QACf,iBAAiB,OAAA,CAAQ,eAAA;AAAA,QACzB,eAAe,OAAA,CAAQ,aAAA;AAAA,QACvB,QAAA,EAAU,eAAA;AAAA,QACV;AAAA;AAAA,KACF,EACF;AAAA,GAAA,EACF,CAAA;AAEJ;;;;"}
|