@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.
Files changed (196) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/README.md +22 -0
  3. package/dist/api/FinOpsAgentApi.esm.js +43 -0
  4. package/dist/api/FinOpsAgentApi.esm.js.map +1 -0
  5. package/dist/api/ObservabilityApi.esm.js +568 -0
  6. package/dist/api/ObservabilityApi.esm.js.map +1 -0
  7. package/dist/api/ObserverUrlCache.esm.js +59 -0
  8. package/dist/api/ObserverUrlCache.esm.js.map +1 -0
  9. package/dist/api/RCAAgentApi.esm.js +104 -0
  10. package/dist/api/RCAAgentApi.esm.js.map +1 -0
  11. package/dist/components/Alerts/AlertRow.esm.js +203 -0
  12. package/dist/components/Alerts/AlertRow.esm.js.map +1 -0
  13. package/dist/components/Alerts/AlertsActions.esm.js +77 -0
  14. package/dist/components/Alerts/AlertsActions.esm.js.map +1 -0
  15. package/dist/components/Alerts/AlertsFilter.esm.js +95 -0
  16. package/dist/components/Alerts/AlertsFilter.esm.js.map +1 -0
  17. package/dist/components/Alerts/AlertsTable.esm.js +63 -0
  18. package/dist/components/Alerts/AlertsTable.esm.js.map +1 -0
  19. package/dist/components/Alerts/ObservabilityAlertsPage.esm.js +251 -0
  20. package/dist/components/Alerts/ObservabilityAlertsPage.esm.js.map +1 -0
  21. package/dist/components/Alerts/types.esm.js +4 -0
  22. package/dist/components/Alerts/types.esm.js.map +1 -0
  23. package/dist/components/CostAnalysis/CostAnalysisPage.esm.js +141 -0
  24. package/dist/components/CostAnalysis/CostAnalysisPage.esm.js.map +1 -0
  25. package/dist/components/CostAnalysis/CostAnalysisReport.esm.js +128 -0
  26. package/dist/components/CostAnalysis/CostAnalysisReport.esm.js.map +1 -0
  27. package/dist/components/CostAnalysis/CostAnalysisReportView.esm.js +517 -0
  28. package/dist/components/CostAnalysis/CostAnalysisReportView.esm.js.map +1 -0
  29. package/dist/components/CostAnalysis/CostAnalysisTable.esm.js +149 -0
  30. package/dist/components/CostAnalysis/CostAnalysisTable.esm.js.map +1 -0
  31. package/dist/components/CostAnalysis/FinOpsApplyButton.esm.js +112 -0
  32. package/dist/components/CostAnalysis/FinOpsApplyButton.esm.js.map +1 -0
  33. package/dist/components/CostAnalysis/index.esm.js +2 -0
  34. package/dist/components/CostAnalysis/index.esm.js.map +1 -0
  35. package/dist/components/Incidents/IncidentRow.esm.js +258 -0
  36. package/dist/components/Incidents/IncidentRow.esm.js.map +1 -0
  37. package/dist/components/Incidents/IncidentsActions.esm.js +77 -0
  38. package/dist/components/Incidents/IncidentsActions.esm.js.map +1 -0
  39. package/dist/components/Incidents/IncidentsFilter.esm.js +144 -0
  40. package/dist/components/Incidents/IncidentsFilter.esm.js.map +1 -0
  41. package/dist/components/Incidents/IncidentsTable.esm.js +68 -0
  42. package/dist/components/Incidents/IncidentsTable.esm.js.map +1 -0
  43. package/dist/components/Incidents/ObservabilityProjectIncidentsPage.esm.js +283 -0
  44. package/dist/components/Incidents/ObservabilityProjectIncidentsPage.esm.js.map +1 -0
  45. package/dist/components/Incidents/types.esm.js +8 -0
  46. package/dist/components/Incidents/types.esm.js.map +1 -0
  47. package/dist/components/Metrics/ChartTooltip.esm.js +53 -0
  48. package/dist/components/Metrics/ChartTooltip.esm.js.map +1 -0
  49. package/dist/components/Metrics/HTTPMetricsSection.esm.js +109 -0
  50. package/dist/components/Metrics/HTTPMetricsSection.esm.js.map +1 -0
  51. package/dist/components/Metrics/MetricGraphByComponent.esm.js +99 -0
  52. package/dist/components/Metrics/MetricGraphByComponent.esm.js.map +1 -0
  53. package/dist/components/Metrics/MetricsActions.esm.js +30 -0
  54. package/dist/components/Metrics/MetricsActions.esm.js.map +1 -0
  55. package/dist/components/Metrics/MetricsFilters.esm.js +49 -0
  56. package/dist/components/Metrics/MetricsFilters.esm.js.map +1 -0
  57. package/dist/components/Metrics/ObservabilityMetricsPage.esm.js +196 -0
  58. package/dist/components/Metrics/ObservabilityMetricsPage.esm.js.map +1 -0
  59. package/dist/components/Metrics/styles.esm.js +55 -0
  60. package/dist/components/Metrics/styles.esm.js.map +1 -0
  61. package/dist/components/Metrics/utils.esm.js +221 -0
  62. package/dist/components/Metrics/utils.esm.js.map +1 -0
  63. package/dist/components/RCA/RCAActions.esm.js +42 -0
  64. package/dist/components/RCA/RCAActions.esm.js.map +1 -0
  65. package/dist/components/RCA/RCAFilters.esm.js +100 -0
  66. package/dist/components/RCA/RCAFilters.esm.js.map +1 -0
  67. package/dist/components/RCA/RCAPage.esm.js +137 -0
  68. package/dist/components/RCA/RCAPage.esm.js.map +1 -0
  69. package/dist/components/RCA/RCAReport/EntityLinkContext.esm.js +9 -0
  70. package/dist/components/RCA/RCAReport/EntityLinkContext.esm.js.map +1 -0
  71. package/dist/components/RCA/RCAReport/FormattedText.esm.js +94 -0
  72. package/dist/components/RCA/RCAReport/FormattedText.esm.js.map +1 -0
  73. package/dist/components/RCA/RCAReport/RCAReportView.esm.js +308 -0
  74. package/dist/components/RCA/RCAReport/RCAReportView.esm.js.map +1 -0
  75. package/dist/components/RCA/RCAReport/sections/AssessmentSection.esm.js +113 -0
  76. package/dist/components/RCA/RCAReport/sections/AssessmentSection.esm.js.map +1 -0
  77. package/dist/components/RCA/RCAReport/sections/ChatPanelSection.esm.js +272 -0
  78. package/dist/components/RCA/RCAReport/sections/ChatPanelSection.esm.js.map +1 -0
  79. package/dist/components/RCA/RCAReport/sections/ExcludedCausesSection.esm.js +48 -0
  80. package/dist/components/RCA/RCAReport/sections/ExcludedCausesSection.esm.js.map +1 -0
  81. package/dist/components/RCA/RCAReport/sections/IncidentOverviewSection.esm.js +205 -0
  82. package/dist/components/RCA/RCAReport/sections/IncidentOverviewSection.esm.js.map +1 -0
  83. package/dist/components/RCA/RCAReport/sections/InvestigationPathSection.esm.js +121 -0
  84. package/dist/components/RCA/RCAReport/sections/InvestigationPathSection.esm.js.map +1 -0
  85. package/dist/components/RCA/RCAReport/sections/PatchTabContent.esm.js +593 -0
  86. package/dist/components/RCA/RCAReport/sections/PatchTabContent.esm.js.map +1 -0
  87. package/dist/components/RCA/RCAReport/sections/QuickFixesPanelSection.esm.js +35 -0
  88. package/dist/components/RCA/RCAReport/sections/QuickFixesPanelSection.esm.js.map +1 -0
  89. package/dist/components/RCA/RCAReport/sections/RecommendationsSection.esm.js +54 -0
  90. package/dist/components/RCA/RCAReport/sections/RecommendationsSection.esm.js.map +1 -0
  91. package/dist/components/RCA/RCAReport/sections/RootCausesSection.esm.js +526 -0
  92. package/dist/components/RCA/RCAReport/sections/RootCausesSection.esm.js.map +1 -0
  93. package/dist/components/RCA/RCAReport/sections/SystemTimelineSection.esm.js +70 -0
  94. package/dist/components/RCA/RCAReport/sections/SystemTimelineSection.esm.js.map +1 -0
  95. package/dist/components/RCA/RCAReport/sections/VisibilityImprovementsSection.esm.js +54 -0
  96. package/dist/components/RCA/RCAReport/sections/VisibilityImprovementsSection.esm.js.map +1 -0
  97. package/dist/components/RCA/RCAReport/styles.esm.js +467 -0
  98. package/dist/components/RCA/RCAReport/styles.esm.js.map +1 -0
  99. package/dist/components/RCA/RCAReport.esm.js +109 -0
  100. package/dist/components/RCA/RCAReport.esm.js.map +1 -0
  101. package/dist/components/RCA/RCATable.esm.js +140 -0
  102. package/dist/components/RCA/RCATable.esm.js.map +1 -0
  103. package/dist/components/RuntimeLogs/LogEntry.esm.js +182 -0
  104. package/dist/components/RuntimeLogs/LogEntry.esm.js.map +1 -0
  105. package/dist/components/RuntimeLogs/LogsActions.esm.js +106 -0
  106. package/dist/components/RuntimeLogs/LogsActions.esm.js.map +1 -0
  107. package/dist/components/RuntimeLogs/LogsFilter.esm.js +200 -0
  108. package/dist/components/RuntimeLogs/LogsFilter.esm.js.map +1 -0
  109. package/dist/components/RuntimeLogs/LogsTable.esm.js +91 -0
  110. package/dist/components/RuntimeLogs/LogsTable.esm.js.map +1 -0
  111. package/dist/components/RuntimeLogs/ObservabilityProjectRuntimeLogsPage.esm.js +220 -0
  112. package/dist/components/RuntimeLogs/ObservabilityProjectRuntimeLogsPage.esm.js.map +1 -0
  113. package/dist/components/RuntimeLogs/ObservabilityRuntimeLogsPage.esm.js +222 -0
  114. package/dist/components/RuntimeLogs/ObservabilityRuntimeLogsPage.esm.js.map +1 -0
  115. package/dist/components/RuntimeLogs/styles.esm.js +256 -0
  116. package/dist/components/RuntimeLogs/styles.esm.js.map +1 -0
  117. package/dist/components/RuntimeLogs/types.esm.js +16 -0
  118. package/dist/components/RuntimeLogs/types.esm.js.map +1 -0
  119. package/dist/components/TimeRangeFilter/TimeRangeFilter.esm.js +280 -0
  120. package/dist/components/TimeRangeFilter/TimeRangeFilter.esm.js.map +1 -0
  121. package/dist/components/Traces/ObservabilityTracesPage.esm.js +165 -0
  122. package/dist/components/Traces/ObservabilityTracesPage.esm.js.map +1 -0
  123. package/dist/components/Traces/TracesActions.esm.js +37 -0
  124. package/dist/components/Traces/TracesActions.esm.js.map +1 -0
  125. package/dist/components/Traces/TracesFilters.esm.js +121 -0
  126. package/dist/components/Traces/TracesFilters.esm.js.map +1 -0
  127. package/dist/components/Traces/TracesTable.esm.js +137 -0
  128. package/dist/components/Traces/TracesTable.esm.js.map +1 -0
  129. package/dist/components/Traces/WaterfallView.esm.js +567 -0
  130. package/dist/components/Traces/WaterfallView.esm.js.map +1 -0
  131. package/dist/components/Traces/styles.esm.js +198 -0
  132. package/dist/components/Traces/styles.esm.js.map +1 -0
  133. package/dist/components/Traces/utils.esm.js +19 -0
  134. package/dist/components/Traces/utils.esm.js.map +1 -0
  135. package/dist/hooks/useAutoSelectFirstEnvironment.esm.js +25 -0
  136. package/dist/hooks/useAutoSelectFirstEnvironment.esm.js.map +1 -0
  137. package/dist/hooks/useComponentAlerts.esm.js +80 -0
  138. package/dist/hooks/useComponentAlerts.esm.js.map +1 -0
  139. package/dist/hooks/useDataPlaneNetPolProvider.esm.js +55 -0
  140. package/dist/hooks/useDataPlaneNetPolProvider.esm.js.map +1 -0
  141. package/dist/hooks/useDebouncedSearch.esm.js +24 -0
  142. package/dist/hooks/useDebouncedSearch.esm.js.map +1 -0
  143. package/dist/hooks/useFilters.esm.js +29 -0
  144. package/dist/hooks/useFilters.esm.js.map +1 -0
  145. package/dist/hooks/useFinOpsReport.esm.js +66 -0
  146. package/dist/hooks/useFinOpsReport.esm.js.map +1 -0
  147. package/dist/hooks/useFinOpsReports.esm.js +70 -0
  148. package/dist/hooks/useFinOpsReports.esm.js.map +1 -0
  149. package/dist/hooks/useGetComponentsByProject.esm.js +57 -0
  150. package/dist/hooks/useGetComponentsByProject.esm.js.map +1 -0
  151. package/dist/hooks/useGetEnvironmentsByNamespace.esm.js +53 -0
  152. package/dist/hooks/useGetEnvironmentsByNamespace.esm.js.map +1 -0
  153. package/dist/hooks/useGetNamespaceAndProjectByEntity.esm.js +40 -0
  154. package/dist/hooks/useGetNamespaceAndProjectByEntity.esm.js.map +1 -0
  155. package/dist/hooks/useMetrics.esm.js +107 -0
  156. package/dist/hooks/useMetrics.esm.js.map +1 -0
  157. package/dist/hooks/useProjectIncidents.esm.js +111 -0
  158. package/dist/hooks/useProjectIncidents.esm.js.map +1 -0
  159. package/dist/hooks/useProjectRuntimeLogs.esm.js +185 -0
  160. package/dist/hooks/useProjectRuntimeLogs.esm.js.map +1 -0
  161. package/dist/hooks/useRCAReportByAlert.esm.js +54 -0
  162. package/dist/hooks/useRCAReportByAlert.esm.js.map +1 -0
  163. package/dist/hooks/useRCAReports.esm.js +75 -0
  164. package/dist/hooks/useRCAReports.esm.js.map +1 -0
  165. package/dist/hooks/useRuntimeLogs.esm.js +147 -0
  166. package/dist/hooks/useRuntimeLogs.esm.js.map +1 -0
  167. package/dist/hooks/useSpanDetails.esm.js +71 -0
  168. package/dist/hooks/useSpanDetails.esm.js.map +1 -0
  169. package/dist/hooks/useTraceSpans.esm.js +80 -0
  170. package/dist/hooks/useTraceSpans.esm.js.map +1 -0
  171. package/dist/hooks/useTraces.esm.js +112 -0
  172. package/dist/hooks/useTraces.esm.js.map +1 -0
  173. package/dist/hooks/useUpdateIncident.esm.js +50 -0
  174. package/dist/hooks/useUpdateIncident.esm.js.map +1 -0
  175. package/dist/hooks/useUrlFilters.esm.js +63 -0
  176. package/dist/hooks/useUrlFilters.esm.js.map +1 -0
  177. package/dist/hooks/useUrlFiltersForAlerts.esm.js +80 -0
  178. package/dist/hooks/useUrlFiltersForAlerts.esm.js.map +1 -0
  179. package/dist/hooks/useUrlFiltersForIncidents.esm.js +87 -0
  180. package/dist/hooks/useUrlFiltersForIncidents.esm.js.map +1 -0
  181. package/dist/hooks/useUrlFiltersForRuntimeLogs.esm.js +135 -0
  182. package/dist/hooks/useUrlFiltersForRuntimeLogs.esm.js.map +1 -0
  183. package/dist/index.d.ts +41 -0
  184. package/dist/index.esm.js +2 -0
  185. package/dist/index.esm.js.map +1 -0
  186. package/dist/plugin.esm.js +107 -0
  187. package/dist/plugin.esm.js.map +1 -0
  188. package/dist/routes.esm.js +8 -0
  189. package/dist/routes.esm.js.map +1 -0
  190. package/dist/types.esm.js +18 -0
  191. package/dist/types.esm.js.map +1 -0
  192. package/dist/utils/applyResourceChange.esm.js +79 -0
  193. package/dist/utils/applyResourceChange.esm.js.map +1 -0
  194. package/dist/utils/urlTimeRange.esm.js +52 -0
  195. package/dist/utils/urlTimeRange.esm.js.map +1 -0
  196. package/package.json +81 -0
@@ -0,0 +1,109 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { useState, useEffect } from 'react';
3
+ import { useParams, useNavigate } from 'react-router-dom';
4
+ import { Typography, Box } from '@material-ui/core';
5
+ import { Progress } from '@backstage/core-components';
6
+ import { Alert } from '@material-ui/lab';
7
+ import { useRcaPermission, ForbiddenState } from '@openchoreo/backstage-plugin-react';
8
+ import { useEntity } from '@backstage/plugin-catalog-react';
9
+ import { CHOREO_ANNOTATIONS } from '@openchoreo/backstage-plugin-common';
10
+ import { useApi, discoveryApiRef } from '@backstage/core-plugin-api';
11
+ import { useGetEnvironmentsByNamespace } from '../../hooks/useGetEnvironmentsByNamespace.esm.js';
12
+ import { useFilters } from '../../hooks/useFilters.esm.js';
13
+ import '../../utils/urlTimeRange.esm.js';
14
+ import '../../api/ObservabilityApi.esm.js';
15
+ import { useRCAReport } from '../../hooks/useRCAReportByAlert.esm.js';
16
+ import { rcaAgentApiRef } from '../../api/RCAAgentApi.esm.js';
17
+ import '../../api/FinOpsAgentApi.esm.js';
18
+ import { RCAReportView } from './RCAReport/RCAReportView.esm.js';
19
+
20
+ const RCAReportContent = () => {
21
+ const { reportId } = useParams();
22
+ const navigate = useNavigate();
23
+ const { entity } = useEntity();
24
+ const { filters } = useFilters();
25
+ const rcaAgentApi = useApi(rcaAgentApiRef);
26
+ const discoveryApi = useApi(discoveryApiRef);
27
+ const namespace = entity.metadata.annotations?.[CHOREO_ANNOTATIONS.NAMESPACE];
28
+ const projectName = entity.metadata.name;
29
+ const { environments } = useGetEnvironmentsByNamespace(
30
+ namespace,
31
+ projectName
32
+ );
33
+ const environment = filters.environment || environments[0];
34
+ const {
35
+ report: detailedReport,
36
+ loading,
37
+ error
38
+ } = useRCAReport(reportId, environment?.name, entity);
39
+ const [backendBaseUrl, setBackendBaseUrl] = useState();
40
+ useEffect(() => {
41
+ discoveryApi.getBaseUrl("openchoreo-observability-backend").then(setBackendBaseUrl).catch(() => {
42
+ });
43
+ }, [discoveryApi]);
44
+ const chatContext = {
45
+ namespaceName: namespace || "",
46
+ environmentName: environment?.name || "",
47
+ projectName,
48
+ rcaAgentApi,
49
+ backendBaseUrl
50
+ };
51
+ if (loading) {
52
+ return /* @__PURE__ */ jsx(Progress, {});
53
+ }
54
+ if (!reportId) {
55
+ return /* @__PURE__ */ jsx(Alert, { severity: "error", children: /* @__PURE__ */ jsx(Typography, { variant: "body1", children: "Report ID is required" }) });
56
+ }
57
+ if (error) {
58
+ let errorMessage = error;
59
+ let severity = "error";
60
+ if (error.includes("RCA service is not configured")) {
61
+ errorMessage = "AI RCA is not configured. Enable it to view RCA reports.";
62
+ severity = "info";
63
+ } else if (error.includes("Observability is not enabled")) {
64
+ errorMessage = "Observability is not enabled for this environment. Enable observability and enable the AI RCA agent.";
65
+ severity = "info";
66
+ }
67
+ return /* @__PURE__ */ jsx(Box, { mt: 2, mb: 2, children: /* @__PURE__ */ jsx(Alert, { severity, children: /* @__PURE__ */ jsx(Typography, { variant: "body1", children: errorMessage }) }) });
68
+ }
69
+ if (!detailedReport) {
70
+ return null;
71
+ }
72
+ const handleBack = () => {
73
+ navigate(-1);
74
+ };
75
+ return /* @__PURE__ */ jsx(
76
+ RCAReportView,
77
+ {
78
+ report: detailedReport,
79
+ reportId,
80
+ onBack: handleBack,
81
+ chatContext
82
+ }
83
+ );
84
+ };
85
+ const RCAReport = () => {
86
+ const {
87
+ canViewRca,
88
+ loading: permissionLoading,
89
+ deniedTooltip,
90
+ permissionName
91
+ } = useRcaPermission();
92
+ if (permissionLoading) {
93
+ return /* @__PURE__ */ jsx(Progress, {});
94
+ }
95
+ if (!canViewRca) {
96
+ return /* @__PURE__ */ jsx(
97
+ ForbiddenState,
98
+ {
99
+ message: deniedTooltip,
100
+ permissionName,
101
+ variant: "fullpage"
102
+ }
103
+ );
104
+ }
105
+ return /* @__PURE__ */ jsx(RCAReportContent, {});
106
+ };
107
+
108
+ export { RCAReport };
109
+ //# sourceMappingURL=RCAReport.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RCAReport.esm.js","sources":["../../../src/components/RCA/RCAReport.tsx"],"sourcesContent":["import { useState, useEffect } from 'react';\nimport { useParams, useNavigate } from 'react-router-dom';\nimport { Box, Typography } from '@material-ui/core';\nimport { Progress } from '@backstage/core-components';\nimport { Alert } from '@material-ui/lab';\nimport {\n useRcaPermission,\n ForbiddenState,\n} from '@openchoreo/backstage-plugin-react';\nimport { useEntity } from '@backstage/plugin-catalog-react';\nimport {\n useRCAReport,\n useFilters,\n useGetEnvironmentsByNamespace,\n} from '../../hooks';\nimport { CHOREO_ANNOTATIONS } from '@openchoreo/backstage-plugin-common';\nimport { RCAReportView } from './RCAReport/RCAReportView';\nimport { useApi, discoveryApiRef } from '@backstage/core-plugin-api';\nimport { rcaAgentApiRef } from '../../api/RCAAgentApi';\n\nconst RCAReportContent = () => {\n const { reportId } = useParams<{ reportId: string }>();\n const navigate = useNavigate();\n const { entity } = useEntity();\n const { filters } = useFilters();\n const rcaAgentApi = useApi(rcaAgentApiRef);\n const discoveryApi = useApi(discoveryApiRef);\n const namespace = entity.metadata.annotations?.[CHOREO_ANNOTATIONS.NAMESPACE];\n const projectName = entity.metadata.name as string;\n\n // Get environments to ensure we have environment data\n const { environments } = useGetEnvironmentsByNamespace(\n namespace,\n projectName,\n );\n const environment = filters.environment || environments[0];\n\n const {\n report: detailedReport,\n loading,\n error,\n } = useRCAReport(reportId, environment?.name, entity);\n\n const [backendBaseUrl, setBackendBaseUrl] = useState<string | undefined>();\n useEffect(() => {\n discoveryApi\n .getBaseUrl('openchoreo-observability-backend')\n .then(setBackendBaseUrl)\n .catch(() => {});\n }, [discoveryApi]);\n\n const chatContext = {\n namespaceName: namespace || '',\n environmentName: environment?.name || '',\n projectName,\n rcaAgentApi,\n backendBaseUrl,\n };\n\n if (loading) {\n return <Progress />;\n }\n\n if (!reportId) {\n return (\n <Alert severity=\"error\">\n <Typography variant=\"body1\">Report ID is required</Typography>\n </Alert>\n );\n }\n\n if (error) {\n let errorMessage = error;\n let severity: 'info' | 'error' = 'error';\n\n if (error.includes('RCA service is not configured')) {\n errorMessage = 'AI RCA is not configured. Enable it to view RCA reports.';\n severity = 'info';\n } else if (error.includes('Observability is not enabled')) {\n errorMessage =\n 'Observability is not enabled for this environment. Enable observability and enable the AI RCA agent.';\n severity = 'info';\n }\n\n return (\n <Box mt={2} mb={2}>\n <Alert severity={severity}>\n <Typography variant=\"body1\">{errorMessage}</Typography>\n </Alert>\n </Box>\n );\n }\n\n if (!detailedReport) {\n return null;\n }\n\n const handleBack = () => {\n navigate(-1);\n };\n\n return (\n <RCAReportView\n report={detailedReport}\n reportId={reportId}\n onBack={handleBack}\n chatContext={chatContext}\n />\n );\n};\n\nexport const RCAReport = () => {\n const {\n canViewRca,\n loading: permissionLoading,\n deniedTooltip,\n permissionName,\n } = useRcaPermission();\n\n if (permissionLoading) {\n return <Progress />;\n }\n\n if (!canViewRca) {\n return (\n <ForbiddenState\n message={deniedTooltip}\n permissionName={permissionName}\n variant=\"fullpage\"\n />\n );\n }\n\n return <RCAReportContent />;\n};\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,140 @@
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
+ import { Link } from 'react-router-dom';
3
+ import { Table } from '@backstage/core-components';
4
+ import { makeStyles, Box, Typography, Tooltip, IconButton } from '@material-ui/core';
5
+ import DescriptionOutlinedIcon from '@material-ui/icons/DescriptionOutlined';
6
+ import Refresh from '@material-ui/icons/Refresh';
7
+ import { StatusBadge } from '@openchoreo/backstage-design-system';
8
+ import { FormattedText } from './RCAReport/FormattedText.esm.js';
9
+
10
+ const useStyles = makeStyles({
11
+ truncateSingleLine: {
12
+ display: "block",
13
+ overflow: "hidden",
14
+ textOverflow: "ellipsis",
15
+ whiteSpace: "nowrap",
16
+ maxWidth: "100%"
17
+ },
18
+ truncateTwoLines: {
19
+ display: "-webkit-box",
20
+ WebkitLineClamp: 2,
21
+ WebkitBoxOrient: "vertical",
22
+ overflow: "hidden",
23
+ textOverflow: "ellipsis",
24
+ maxWidth: "100%"
25
+ }
26
+ });
27
+ const RCATable = ({ reports, loading = false }) => {
28
+ const classes = useStyles();
29
+ const mapStatusToStatusType = (status) => {
30
+ switch (status) {
31
+ case "completed":
32
+ return "success";
33
+ case "failed":
34
+ return "failed";
35
+ case "pending":
36
+ return "pending";
37
+ default:
38
+ return "unknown";
39
+ }
40
+ };
41
+ const formatTimestamp = (timestamp) => {
42
+ if (!timestamp) return "N/A";
43
+ try {
44
+ return new Date(timestamp).toLocaleString();
45
+ } catch {
46
+ return timestamp;
47
+ }
48
+ };
49
+ const columns = [
50
+ {
51
+ title: "Timestamp",
52
+ field: "timestamp",
53
+ width: "13%",
54
+ render: (row) => {
55
+ const report = row;
56
+ return /* @__PURE__ */ jsx(Typography, { variant: "body2", className: classes.truncateSingleLine, children: formatTimestamp(report.timestamp) });
57
+ }
58
+ },
59
+ {
60
+ title: "Summary",
61
+ field: "summary",
62
+ width: "66%",
63
+ highlight: true,
64
+ render: (row) => {
65
+ const report = row;
66
+ if (report.status === "pending") {
67
+ return /* @__PURE__ */ jsx(Typography, { variant: "body2", children: "Generating RCA report..." });
68
+ }
69
+ return /* @__PURE__ */ jsx(Typography, { variant: "body2", className: classes.truncateTwoLines, children: report.summary ? /* @__PURE__ */ jsx(
70
+ FormattedText,
71
+ {
72
+ text: report.summary,
73
+ disableLinks: true,
74
+ disableMarkdown: true
75
+ }
76
+ ) : "No summary available" });
77
+ }
78
+ },
79
+ {
80
+ title: "Report Status",
81
+ field: "status",
82
+ width: "14%",
83
+ render: (row) => {
84
+ const report = row;
85
+ const status = mapStatusToStatusType(report.status);
86
+ const labelMap = {
87
+ success: "Available",
88
+ pending: "Pending",
89
+ failed: "Failed"
90
+ };
91
+ return /* @__PURE__ */ jsx(StatusBadge, { status, label: labelMap[status] || status });
92
+ }
93
+ },
94
+ {
95
+ title: "Actions",
96
+ field: "actions",
97
+ width: "7%",
98
+ render: (row) => {
99
+ const report = row;
100
+ const isCompleted = report.status === "completed";
101
+ const isFailed = report.status === "failed";
102
+ return /* @__PURE__ */ jsxs(Box, { display: "flex", alignItems: "center", justifyContent: "center", children: [
103
+ isCompleted && /* @__PURE__ */ jsx(Tooltip, { title: "View report", children: /* @__PURE__ */ jsx(
104
+ IconButton,
105
+ {
106
+ size: "small",
107
+ component: Link,
108
+ to: `./${report.reportId}`,
109
+ "aria-label": "view report",
110
+ children: /* @__PURE__ */ jsx(DescriptionOutlinedIcon, { fontSize: "small" })
111
+ }
112
+ ) }),
113
+ isFailed && /* @__PURE__ */ jsx(Tooltip, { title: "Rerun report", children: /* @__PURE__ */ jsx("span", { children: /* @__PURE__ */ jsx(IconButton, { size: "small", "aria-label": "rerun report", disabled: true, children: /* @__PURE__ */ jsx(Refresh, { fontSize: "small" }) }) }) })
114
+ ] });
115
+ }
116
+ }
117
+ ];
118
+ return /* @__PURE__ */ jsx(
119
+ Table,
120
+ {
121
+ options: {
122
+ search: false,
123
+ toolbar: false,
124
+ paging: false,
125
+ sorting: true,
126
+ padding: "default"
127
+ },
128
+ columns,
129
+ data: reports,
130
+ isLoading: loading,
131
+ emptyContent: /* @__PURE__ */ jsxs(Box, { textAlign: "center", padding: 4, children: [
132
+ /* @__PURE__ */ jsx(Typography, { variant: "h6", gutterBottom: true, children: "No RCA reports found" }),
133
+ /* @__PURE__ */ jsx(Typography, { variant: "body2", color: "textSecondary", children: "Try adjusting your filters or time range to see more reports." })
134
+ ] })
135
+ }
136
+ );
137
+ };
138
+
139
+ export { RCATable };
140
+ //# sourceMappingURL=RCATable.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RCATable.esm.js","sources":["../../../src/components/RCA/RCATable.tsx"],"sourcesContent":["import { Link as RouterLink } from 'react-router-dom';\nimport { Table, TableColumn } from '@backstage/core-components';\nimport {\n Box,\n Typography,\n IconButton,\n Tooltip,\n makeStyles,\n} from '@material-ui/core';\nimport DescriptionOutlinedIcon from '@material-ui/icons/DescriptionOutlined';\nimport RefreshIcon from '@material-ui/icons/Refresh';\nimport { StatusBadge, StatusType } from '@openchoreo/backstage-design-system';\nimport { RCAReportSummary } from '../../types';\nimport { FormattedText } from './RCAReport/FormattedText';\n\nconst useStyles = makeStyles({\n truncateSingleLine: {\n display: 'block',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n maxWidth: '100%',\n },\n truncateTwoLines: {\n display: '-webkit-box',\n WebkitLineClamp: 2,\n WebkitBoxOrient: 'vertical',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n maxWidth: '100%',\n },\n});\n\ninterface RCATableProps {\n reports: RCAReportSummary[];\n loading?: boolean;\n}\n\nexport const RCATable = ({ reports, loading = false }: RCATableProps) => {\n const classes = useStyles();\n const mapStatusToStatusType = (\n status?: 'pending' | 'completed' | 'failed',\n ): StatusType => {\n switch (status) {\n case 'completed':\n return 'success';\n case 'failed':\n return 'failed';\n case 'pending':\n return 'pending';\n default:\n return 'unknown';\n }\n };\n\n const formatTimestamp = (timestamp?: string): string => {\n if (!timestamp) return 'N/A';\n try {\n return new Date(timestamp).toLocaleString();\n } catch {\n return timestamp;\n }\n };\n\n const columns: TableColumn[] = [\n {\n title: 'Timestamp',\n field: 'timestamp',\n width: '13%',\n render: (row: any) => {\n const report = row as RCAReportSummary;\n return (\n <Typography variant=\"body2\" className={classes.truncateSingleLine}>\n {formatTimestamp(report.timestamp)}\n </Typography>\n );\n },\n },\n {\n title: 'Summary',\n field: 'summary',\n width: '66%',\n highlight: true,\n render: (row: any) => {\n const report = row as RCAReportSummary;\n if (report.status === 'pending') {\n return (\n <Typography variant=\"body2\">Generating RCA report...</Typography>\n );\n }\n return (\n <Typography variant=\"body2\" className={classes.truncateTwoLines}>\n {report.summary ? (\n <FormattedText\n text={report.summary}\n disableLinks\n disableMarkdown\n />\n ) : (\n 'No summary available'\n )}\n </Typography>\n );\n },\n },\n {\n title: 'Report Status',\n field: 'status',\n width: '14%',\n render: (row: any) => {\n const report = row as RCAReportSummary;\n const status = mapStatusToStatusType(report.status);\n const labelMap: Record<string, string> = {\n success: 'Available',\n pending: 'Pending',\n failed: 'Failed',\n };\n return (\n <StatusBadge status={status} label={labelMap[status] || status} />\n );\n },\n },\n {\n title: 'Actions',\n field: 'actions',\n width: '7%',\n render: (row: any) => {\n const report = row as RCAReportSummary;\n const isCompleted = report.status === 'completed';\n const isFailed = report.status === 'failed';\n return (\n <Box display=\"flex\" alignItems=\"center\" justifyContent=\"center\">\n {isCompleted && (\n <Tooltip title=\"View report\">\n <IconButton\n size=\"small\"\n component={RouterLink}\n to={`./${report.reportId}`}\n aria-label=\"view report\"\n >\n <DescriptionOutlinedIcon fontSize=\"small\" />\n </IconButton>\n </Tooltip>\n )}\n {isFailed && (\n <Tooltip title=\"Rerun report\">\n <span>\n <IconButton size=\"small\" aria-label=\"rerun report\" disabled>\n <RefreshIcon fontSize=\"small\" />\n </IconButton>\n </span>\n </Tooltip>\n )}\n </Box>\n );\n },\n },\n ];\n\n return (\n <Table\n options={{\n search: false,\n toolbar: false,\n paging: false,\n sorting: true,\n padding: 'default',\n }}\n columns={columns}\n data={reports}\n isLoading={loading}\n emptyContent={\n <Box textAlign=\"center\" padding={4}>\n <Typography variant=\"h6\" gutterBottom>\n No RCA reports found\n </Typography>\n <Typography variant=\"body2\" color=\"textSecondary\">\n Try adjusting your filters or time range to see more reports.\n </Typography>\n </Box>\n }\n />\n );\n};\n"],"names":["RouterLink","RefreshIcon"],"mappings":"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"}
@@ -0,0 +1,182 @@
1
+ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
2
+ import { useState } from 'react';
3
+ import { TableRow, TableCell, Chip, Box, Typography, Tooltip, IconButton, Collapse } from '@material-ui/core';
4
+ import FileCopyOutlined from '@material-ui/icons/FileCopyOutlined';
5
+ import { LogEntryField } from './types.esm.js';
6
+ import { useLogEntryStyles } from './styles.esm.js';
7
+
8
+ const LogEntry = ({
9
+ log,
10
+ selectedFields,
11
+ environmentName,
12
+ projectName,
13
+ componentName,
14
+ getLogsSnapshot,
15
+ renderRowAction
16
+ }) => {
17
+ const classes = useLogEntryStyles();
18
+ const [expanded, setExpanded] = useState(false);
19
+ const [copySuccess, setCopySuccess] = useState(false);
20
+ const handleRowClick = () => {
21
+ setExpanded(!expanded);
22
+ };
23
+ const handleCopyLog = async (event) => {
24
+ event.stopPropagation();
25
+ if (!navigator.clipboard?.writeText) {
26
+ return;
27
+ }
28
+ try {
29
+ await navigator.clipboard.writeText(log.log ?? "");
30
+ setCopySuccess(true);
31
+ setTimeout(() => setCopySuccess(false), 2e3);
32
+ } catch (err) {
33
+ }
34
+ };
35
+ const getLogLevelChipClass = (level) => {
36
+ switch (level) {
37
+ case "ERROR":
38
+ return classes.errorChip;
39
+ case "WARN":
40
+ return classes.warnChip;
41
+ case "INFO":
42
+ return classes.infoChip;
43
+ case "DEBUG":
44
+ return classes.debugChip;
45
+ case "UNDEFINED":
46
+ return classes.undefinedChip;
47
+ default:
48
+ return "";
49
+ }
50
+ };
51
+ const formatTimestamp = (timestamp) => {
52
+ return new Date(timestamp).toLocaleString();
53
+ };
54
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
55
+ /* @__PURE__ */ jsx(
56
+ TableRow,
57
+ {
58
+ className: `${classes.logRow} ${expanded ? classes.expandedRow : ""}`,
59
+ onClick: handleRowClick,
60
+ children: selectedFields.map((field) => {
61
+ if (field === LogEntryField.Timestamp) {
62
+ return /* @__PURE__ */ jsx(TableCell, { className: classes.monospaceCell, children: formatTimestamp(log.timestamp ?? "") }, field);
63
+ }
64
+ if (field === LogEntryField.LogLevel) {
65
+ return /* @__PURE__ */ jsx(TableCell, { children: /* @__PURE__ */ jsx(
66
+ Chip,
67
+ {
68
+ label: log.level,
69
+ size: "small",
70
+ className: `${classes.logLevelChip} ${getLogLevelChipClass(
71
+ log.level ?? ""
72
+ )}`
73
+ }
74
+ ) }, field);
75
+ }
76
+ if (field === LogEntryField.ComponentName) {
77
+ return /* @__PURE__ */ jsx(TableCell, { className: classes.monospaceCell, children: log.metadata?.componentName ?? componentName ?? "" }, field);
78
+ }
79
+ return /* @__PURE__ */ jsx(TableCell, { className: classes.logCell, children: /* @__PURE__ */ jsxs(Box, { className: classes.logCellContent, children: [
80
+ /* @__PURE__ */ jsx(Box, { className: classes.logTextContainer, children: /* @__PURE__ */ jsx(
81
+ Typography,
82
+ {
83
+ className: `${classes.logMessage} ${expanded ? classes.expandedLogMessage : ""}`,
84
+ children: log.log
85
+ }
86
+ ) }),
87
+ /* @__PURE__ */ jsxs(
88
+ Box,
89
+ {
90
+ className: `${classes.logActionColumn} ${classes.hoverActionButton}`,
91
+ children: [
92
+ /* @__PURE__ */ jsx(Tooltip, { title: copySuccess ? "Copied!" : "Copy log message", children: /* @__PURE__ */ jsx(
93
+ IconButton,
94
+ {
95
+ className: classes.copyButton,
96
+ onClick: handleCopyLog,
97
+ size: "small",
98
+ children: /* @__PURE__ */ jsx(FileCopyOutlined, { fontSize: "inherit" })
99
+ }
100
+ ) }),
101
+ renderRowAction?.(log, getLogsSnapshot)
102
+ ]
103
+ }
104
+ )
105
+ ] }) }, field);
106
+ })
107
+ }
108
+ ),
109
+ expanded && /* @__PURE__ */ jsx(TableRow, { children: /* @__PURE__ */ jsx(
110
+ TableCell,
111
+ {
112
+ colSpan: selectedFields.length,
113
+ style: { paddingBottom: 0, paddingTop: 0 },
114
+ children: /* @__PURE__ */ jsx(Collapse, { in: expanded, timeout: "auto", unmountOnExit: true, children: /* @__PURE__ */ jsxs(Box, { className: classes.expandedContent, children: [
115
+ /* @__PURE__ */ jsx(
116
+ Typography,
117
+ {
118
+ className: classes.expandedSectionTitle,
119
+ gutterBottom: true,
120
+ children: "Full Log Message"
121
+ }
122
+ ),
123
+ /* @__PURE__ */ jsx(Box, { className: classes.fullLogMessage, children: log.log }),
124
+ /* @__PURE__ */ jsxs(Box, { className: classes.metadataSection, children: [
125
+ /* @__PURE__ */ jsx(
126
+ Typography,
127
+ {
128
+ className: `${classes.metadataTitle} ${classes.expandedSectionTitle}`,
129
+ children: "Metadata"
130
+ }
131
+ ),
132
+ /* @__PURE__ */ jsx(Box, { className: classes.metadataBox, children: /* @__PURE__ */ jsxs(Box, { className: classes.metadataGrid, children: [
133
+ /* @__PURE__ */ jsxs(Box, { className: classes.metadataItem, children: [
134
+ /* @__PURE__ */ jsx("span", { className: classes.metadataKey, children: "Environment Name:" }),
135
+ /* @__PURE__ */ jsx("span", { className: classes.metadataValue, children: log.metadata?.environmentName ?? environmentName })
136
+ ] }),
137
+ /* @__PURE__ */ jsxs(Box, { className: classes.metadataItem, children: [
138
+ /* @__PURE__ */ jsx("span", { className: classes.metadataKey, children: "Environment UID:" }),
139
+ /* @__PURE__ */ jsx("span", { className: classes.metadataValue, children: log.metadata?.environmentUid })
140
+ ] }),
141
+ /* @__PURE__ */ jsxs(Box, { className: classes.metadataItem, children: [
142
+ /* @__PURE__ */ jsx("span", { className: classes.metadataKey, children: "Project Name:" }),
143
+ /* @__PURE__ */ jsx("span", { className: classes.metadataValue, children: log.metadata?.projectName ?? projectName })
144
+ ] }),
145
+ /* @__PURE__ */ jsxs(Box, { className: classes.metadataItem, children: [
146
+ /* @__PURE__ */ jsx("span", { className: classes.metadataKey, children: "Project UID:" }),
147
+ /* @__PURE__ */ jsx("span", { className: classes.metadataValue, children: log.metadata?.projectUid })
148
+ ] }),
149
+ /* @__PURE__ */ jsxs(Box, { className: classes.metadataItem, children: [
150
+ /* @__PURE__ */ jsx("span", { className: classes.metadataKey, children: "Component Name:" }),
151
+ /* @__PURE__ */ jsx("span", { className: classes.metadataValue, children: log.metadata?.componentName ?? componentName })
152
+ ] }),
153
+ /* @__PURE__ */ jsxs(Box, { className: classes.metadataItem, children: [
154
+ /* @__PURE__ */ jsx("span", { className: classes.metadataKey, children: "Component UID:" }),
155
+ /* @__PURE__ */ jsx("span", { className: classes.metadataValue, children: log.metadata?.componentUid })
156
+ ] }),
157
+ /* @__PURE__ */ jsxs(Box, { className: classes.metadataItem, children: [
158
+ /* @__PURE__ */ jsx("span", { className: classes.metadataKey, children: "Pod Name:" }),
159
+ /* @__PURE__ */ jsx("span", { className: classes.metadataValue, children: log.metadata?.podName })
160
+ ] }),
161
+ /* @__PURE__ */ jsxs(Box, { className: classes.metadataItem, children: [
162
+ /* @__PURE__ */ jsx("span", { className: classes.metadataKey, children: "Pod Namespace:" }),
163
+ /* @__PURE__ */ jsx("span", { className: classes.metadataValue, children: log.metadata?.podNamespace })
164
+ ] }),
165
+ /* @__PURE__ */ jsxs(Box, { className: classes.metadataItem, children: [
166
+ /* @__PURE__ */ jsx("span", { className: classes.metadataKey, children: "Namespace:" }),
167
+ /* @__PURE__ */ jsx("span", { className: classes.metadataValue, children: log.metadata?.namespaceName })
168
+ ] }),
169
+ /* @__PURE__ */ jsxs(Box, { className: classes.metadataItem, children: [
170
+ /* @__PURE__ */ jsx("span", { className: classes.metadataKey, children: "Container:" }),
171
+ /* @__PURE__ */ jsx("span", { className: classes.metadataValue, children: log.metadata?.containerName })
172
+ ] })
173
+ ] }) })
174
+ ] })
175
+ ] }) })
176
+ }
177
+ ) })
178
+ ] });
179
+ };
180
+
181
+ export { LogEntry };
182
+ //# sourceMappingURL=LogEntry.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LogEntry.esm.js","sources":["../../../src/components/RuntimeLogs/LogEntry.tsx"],"sourcesContent":["import { FC, MouseEvent, ReactNode, useState } from 'react';\nimport {\n TableRow,\n TableCell,\n Typography,\n Chip,\n Box,\n Collapse,\n IconButton,\n Tooltip,\n} from '@material-ui/core';\nimport FileCopyOutlined from '@material-ui/icons/FileCopyOutlined';\nimport { LogEntry as LogEntryType, LogEntryField } from './types';\nimport { useLogEntryStyles } from './styles';\n\n/**\n * Render-prop slot for a per-row action button (assistant integration,\n * \"open in external tool\", etc.). The host app supplies this from\n * outside the plugin so observability stays free of cross-plugin\n * coupling. When omitted, no action button is rendered.\n */\nexport type RenderLogRowAction = (\n log: LogEntryType,\n getLogsSnapshot?: () => LogEntryType[],\n) => ReactNode;\n\ninterface LogEntryProps {\n log: LogEntryType;\n selectedFields: LogEntryField[];\n environmentName?: string;\n projectName?: string;\n componentName?: string;\n /**\n * Stable callback (typically backed by a ref) returning the table's\n * current log rows. Forwarded to ``renderRowAction`` so an assistant\n * integration can skip a first round-trip by prefetching what the\n * user is staring at. The closure-via-ref shape keeps row re-renders\n * cheap when new logs stream in — children see a stable reference.\n */\n getLogsSnapshot?: () => LogEntryType[];\n renderRowAction?: RenderLogRowAction;\n}\n\nexport const LogEntry: FC<LogEntryProps> = ({\n log,\n selectedFields,\n environmentName,\n projectName,\n componentName,\n getLogsSnapshot,\n renderRowAction,\n}) => {\n const classes = useLogEntryStyles();\n const [expanded, setExpanded] = useState(false);\n const [copySuccess, setCopySuccess] = useState(false);\n\n const handleRowClick = () => {\n setExpanded(!expanded);\n };\n\n const handleCopyLog = async (event: MouseEvent<HTMLButtonElement>) => {\n event.stopPropagation();\n\n // Check if clipboard API is available\n if (!navigator.clipboard?.writeText) {\n // Clipboard API not supported or not in secure context\n return;\n }\n\n try {\n await navigator.clipboard.writeText(log.log ?? '');\n setCopySuccess(true);\n setTimeout(() => setCopySuccess(false), 2000);\n } catch (err) {\n // Silent fail - clipboard operation failed\n // Could be due to permissions or other issues\n }\n };\n\n const getLogLevelChipClass = (level: string) => {\n switch (level) {\n case 'ERROR':\n return classes.errorChip;\n case 'WARN':\n return classes.warnChip;\n case 'INFO':\n return classes.infoChip;\n case 'DEBUG':\n return classes.debugChip;\n case 'UNDEFINED':\n return classes.undefinedChip;\n default:\n return '';\n }\n };\n\n const formatTimestamp = (timestamp: string): string => {\n return new Date(timestamp).toLocaleString();\n };\n\n return (\n <>\n <TableRow\n className={`${classes.logRow} ${expanded ? classes.expandedRow : ''}`}\n onClick={handleRowClick}\n >\n {selectedFields.map(field => {\n if (field === LogEntryField.Timestamp) {\n return (\n <TableCell key={field} className={classes.monospaceCell}>\n {formatTimestamp(log.timestamp ?? '')}\n </TableCell>\n );\n }\n\n if (field === LogEntryField.LogLevel) {\n return (\n <TableCell key={field}>\n <Chip\n label={log.level}\n size=\"small\"\n className={`${classes.logLevelChip} ${getLogLevelChipClass(\n log.level ?? '',\n )}`}\n />\n </TableCell>\n );\n }\n\n if (field === LogEntryField.ComponentName) {\n return (\n <TableCell key={field} className={classes.monospaceCell}>\n {log.metadata?.componentName ?? componentName ?? ''}\n </TableCell>\n );\n }\n\n return (\n <TableCell key={field} className={classes.logCell}>\n <Box className={classes.logCellContent}>\n <Box className={classes.logTextContainer}>\n <Typography\n className={`${classes.logMessage} ${\n expanded ? classes.expandedLogMessage : ''\n }`}\n >\n {log.log}\n </Typography>\n </Box>\n <Box\n className={`${classes.logActionColumn} ${classes.hoverActionButton}`}\n >\n <Tooltip title={copySuccess ? 'Copied!' : 'Copy log message'}>\n <IconButton\n className={classes.copyButton}\n onClick={handleCopyLog}\n size=\"small\"\n >\n <FileCopyOutlined fontSize=\"inherit\" />\n </IconButton>\n </Tooltip>\n {/* Host-supplied per-row action (e.g. assistant\n \"Investigate\" button). Injected from outside this\n plugin so observability owns no cross-plugin\n dependency. Falsy renderRowAction → nothing\n mounts, identical to the slot being absent. */}\n {renderRowAction?.(log, getLogsSnapshot)}\n </Box>\n </Box>\n </TableCell>\n );\n })}\n </TableRow>\n\n {expanded && (\n <TableRow>\n <TableCell\n colSpan={selectedFields.length}\n style={{ paddingBottom: 0, paddingTop: 0 }}\n >\n <Collapse in={expanded} timeout=\"auto\" unmountOnExit>\n <Box className={classes.expandedContent}>\n <Typography\n className={classes.expandedSectionTitle}\n gutterBottom\n >\n Full Log Message\n </Typography>\n <Box className={classes.fullLogMessage}>{log.log}</Box>\n\n <Box className={classes.metadataSection}>\n <Typography\n className={`${classes.metadataTitle} ${classes.expandedSectionTitle}`}\n >\n Metadata\n </Typography>\n\n <Box className={classes.metadataBox}>\n <Box className={classes.metadataGrid}>\n <Box className={classes.metadataItem}>\n <span className={classes.metadataKey}>\n Environment Name:\n </span>\n <span className={classes.metadataValue}>\n {log.metadata?.environmentName ?? environmentName}\n </span>\n </Box>\n\n <Box className={classes.metadataItem}>\n <span className={classes.metadataKey}>\n Environment UID:\n </span>\n <span className={classes.metadataValue}>\n {log.metadata?.environmentUid}\n </span>\n </Box>\n\n <Box className={classes.metadataItem}>\n <span className={classes.metadataKey}>\n Project Name:\n </span>\n <span className={classes.metadataValue}>\n {log.metadata?.projectName ?? projectName}\n </span>\n </Box>\n\n <Box className={classes.metadataItem}>\n <span className={classes.metadataKey}>\n Project UID:\n </span>\n <span className={classes.metadataValue}>\n {log.metadata?.projectUid}\n </span>\n </Box>\n\n <Box className={classes.metadataItem}>\n <span className={classes.metadataKey}>\n Component Name:\n </span>\n <span className={classes.metadataValue}>\n {log.metadata?.componentName ?? componentName}\n </span>\n </Box>\n\n <Box className={classes.metadataItem}>\n <span className={classes.metadataKey}>\n Component UID:\n </span>\n <span className={classes.metadataValue}>\n {log.metadata?.componentUid}\n </span>\n </Box>\n\n <Box className={classes.metadataItem}>\n <span className={classes.metadataKey}>Pod Name:</span>\n <span className={classes.metadataValue}>\n {log.metadata?.podName}\n </span>\n </Box>\n\n <Box className={classes.metadataItem}>\n <span className={classes.metadataKey}>\n Pod Namespace:\n </span>\n <span className={classes.metadataValue}>\n {log.metadata?.podNamespace}\n </span>\n </Box>\n\n <Box className={classes.metadataItem}>\n <span className={classes.metadataKey}>Namespace:</span>\n <span className={classes.metadataValue}>\n {log.metadata?.namespaceName}\n </span>\n </Box>\n\n <Box className={classes.metadataItem}>\n <span className={classes.metadataKey}>Container:</span>\n <span className={classes.metadataValue}>\n {log.metadata?.containerName}\n </span>\n </Box>\n </Box>\n </Box>\n </Box>\n </Box>\n </Collapse>\n </TableCell>\n </TableRow>\n )}\n </>\n );\n};\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,106 @@
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import { Box, Typography, Tooltip, Button } from '@material-ui/core';
3
+ import Refresh from '@material-ui/icons/Refresh';
4
+ import FiberManualRecord from '@material-ui/icons/FiberManualRecord';
5
+ import { useLogsActionsStyles } from './styles.esm.js';
6
+ import ArrowUpward from '@material-ui/icons/ArrowUpward';
7
+ import ArrowDownward from '@material-ui/icons/ArrowDownward';
8
+
9
+ const formatDate = (date) => {
10
+ const day = String(date.getDate()).padStart(2, "0");
11
+ const month = String(date.getMonth() + 1).padStart(2, "0");
12
+ const year = date.getFullYear();
13
+ const hours = String(date.getHours()).padStart(2, "0");
14
+ const minutes = String(date.getMinutes()).padStart(2, "0");
15
+ const seconds = String(date.getSeconds()).padStart(2, "0");
16
+ return `${day}/${month}/${year}, ${hours}:${minutes}:${seconds}`;
17
+ };
18
+ const LogsActions = ({
19
+ totalCount,
20
+ disabled,
21
+ onRefresh,
22
+ filters,
23
+ onFiltersChange,
24
+ lastUpdated
25
+ }) => {
26
+ const classes = useLogsActionsStyles();
27
+ const effectiveSortOrder = filters.sortOrder || "desc";
28
+ const handleSortToggle = () => {
29
+ const newSortOrder = effectiveSortOrder === "desc" ? "asc" : "desc";
30
+ onFiltersChange({ sortOrder: newSortOrder });
31
+ };
32
+ const handleLiveToggle = () => {
33
+ onFiltersChange({ isLive: !filters.isLive });
34
+ };
35
+ const displayDate = lastUpdated || /* @__PURE__ */ new Date();
36
+ return /* @__PURE__ */ jsxs(Box, { className: classes.statsContainer, children: [
37
+ /* @__PURE__ */ jsxs(Box, { children: [
38
+ /* @__PURE__ */ jsxs(Typography, { variant: "body2", color: "textSecondary", children: [
39
+ "Total logs: ",
40
+ totalCount
41
+ ] }),
42
+ /* @__PURE__ */ jsxs(Typography, { variant: "body2", color: "textSecondary", children: [
43
+ "Last updated at: ",
44
+ formatDate(displayDate)
45
+ ] })
46
+ ] }),
47
+ /* @__PURE__ */ jsxs(Box, { className: classes.actionsContainer, children: [
48
+ /* @__PURE__ */ jsx(
49
+ Tooltip,
50
+ {
51
+ title: effectiveSortOrder === "desc" ? "Sort Logs by Newest First" : "Sort Logs by Oldest First",
52
+ children: /* @__PURE__ */ jsx(
53
+ Button,
54
+ {
55
+ variant: "outlined",
56
+ onClick: handleSortToggle,
57
+ disabled,
58
+ size: "small",
59
+ startIcon: effectiveSortOrder === "desc" ? /* @__PURE__ */ jsx(ArrowUpward, {}) : /* @__PURE__ */ jsx(ArrowDownward, {}),
60
+ children: effectiveSortOrder === "desc" ? "Newest First" : "Oldest First"
61
+ }
62
+ )
63
+ }
64
+ ),
65
+ /* @__PURE__ */ jsx(
66
+ Tooltip,
67
+ {
68
+ title: filters.isLive ? "Stop Live Updates" : "Start Live Updates",
69
+ children: /* @__PURE__ */ jsx(
70
+ Button,
71
+ {
72
+ variant: "outlined",
73
+ onClick: handleLiveToggle,
74
+ disabled,
75
+ size: "small",
76
+ startIcon: /* @__PURE__ */ jsx(
77
+ FiberManualRecord,
78
+ {
79
+ style: {
80
+ color: filters.isLive ? "#4caf50" : "inherit",
81
+ fontSize: "12px"
82
+ }
83
+ }
84
+ ),
85
+ children: "Live"
86
+ }
87
+ )
88
+ }
89
+ ),
90
+ /* @__PURE__ */ jsx(Tooltip, { title: "Refresh", children: /* @__PURE__ */ jsx(
91
+ Button,
92
+ {
93
+ variant: "outlined",
94
+ startIcon: /* @__PURE__ */ jsx(Refresh, {}),
95
+ onClick: onRefresh,
96
+ disabled,
97
+ size: "small",
98
+ children: "Refresh"
99
+ }
100
+ ) })
101
+ ] })
102
+ ] });
103
+ };
104
+
105
+ export { LogsActions };
106
+ //# sourceMappingURL=LogsActions.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LogsActions.esm.js","sources":["../../../src/components/RuntimeLogs/LogsActions.tsx"],"sourcesContent":["import { Box, Typography, Button, Tooltip } from '@material-ui/core';\nimport Refresh from '@material-ui/icons/Refresh';\nimport FiberManualRecord from '@material-ui/icons/FiberManualRecord';\nimport { useLogsActionsStyles } from './styles';\nimport { RuntimeLogsFilters } from './types';\nimport ArrowUpward from '@material-ui/icons/ArrowUpward';\nimport ArrowDownward from '@material-ui/icons/ArrowDownward';\n\ninterface LogsActionsProps {\n totalCount: number;\n disabled: boolean;\n onRefresh: () => void;\n filters: RuntimeLogsFilters;\n onFiltersChange: (filters: Partial<RuntimeLogsFilters>) => void;\n lastUpdated?: Date;\n}\n\nconst formatDate = (date: Date): string => {\n const day = String(date.getDate()).padStart(2, '0');\n const month = String(date.getMonth() + 1).padStart(2, '0');\n const year = date.getFullYear();\n const hours = String(date.getHours()).padStart(2, '0');\n const minutes = String(date.getMinutes()).padStart(2, '0');\n const seconds = String(date.getSeconds()).padStart(2, '0');\n return `${day}/${month}/${year}, ${hours}:${minutes}:${seconds}`;\n};\n\nexport const LogsActions = ({\n totalCount,\n disabled,\n onRefresh,\n filters,\n onFiltersChange,\n lastUpdated,\n}: LogsActionsProps) => {\n const classes = useLogsActionsStyles();\n\n const effectiveSortOrder = filters.sortOrder || 'desc';\n const handleSortToggle = () => {\n const newSortOrder = effectiveSortOrder === 'desc' ? 'asc' : 'desc';\n onFiltersChange({ sortOrder: newSortOrder });\n };\n\n const handleLiveToggle = () => {\n onFiltersChange({ isLive: !filters.isLive });\n };\n\n const displayDate = lastUpdated || new Date();\n\n return (\n <Box className={classes.statsContainer}>\n <Box>\n <Typography variant=\"body2\" color=\"textSecondary\">\n Total logs: {totalCount}\n </Typography>\n <Typography variant=\"body2\" color=\"textSecondary\">\n Last updated at: {formatDate(displayDate)}\n </Typography>\n </Box>\n <Box className={classes.actionsContainer}>\n <Tooltip\n title={\n effectiveSortOrder === 'desc'\n ? 'Sort Logs by Newest First'\n : 'Sort Logs by Oldest First'\n }\n >\n <Button\n variant=\"outlined\"\n onClick={handleSortToggle}\n disabled={disabled}\n size=\"small\"\n startIcon={\n effectiveSortOrder === 'desc' ? (\n <ArrowUpward />\n ) : (\n <ArrowDownward />\n )\n }\n >\n {effectiveSortOrder === 'desc' ? 'Newest First' : 'Oldest First'}\n </Button>\n </Tooltip>\n <Tooltip\n title={filters.isLive ? 'Stop Live Updates' : 'Start Live Updates'}\n >\n <Button\n variant=\"outlined\"\n onClick={handleLiveToggle}\n disabled={disabled}\n size=\"small\"\n startIcon={\n <FiberManualRecord\n style={{\n color: filters.isLive ? '#4caf50' : 'inherit',\n fontSize: '12px',\n }}\n />\n }\n >\n Live\n </Button>\n </Tooltip>\n <Tooltip title=\"Refresh\">\n <Button\n variant=\"outlined\"\n startIcon={<Refresh />}\n onClick={onRefresh}\n disabled={disabled}\n size=\"small\"\n >\n Refresh\n </Button>\n </Tooltip>\n </Box>\n </Box>\n );\n};\n"],"names":[],"mappings":"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"}