@perses-dev/tracing-gantt-chart-plugin 0.8.0 → 0.9.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 (137) hide show
  1. package/__mf/css/async/263.6c6463ea.css +1 -0
  2. package/__mf/js/TracingGanttChart.6861c573.js +5 -0
  3. package/__mf/js/async/109.1225b97d.js +73 -0
  4. package/__mf/js/async/109.1225b97d.js.LICENSE.txt +35 -0
  5. package/__mf/js/async/118.c1138755.js +1 -0
  6. package/__mf/js/async/173.66fc423e.js +2 -0
  7. package/__mf/js/async/214.8bf3e03e.js +1 -0
  8. package/__mf/js/async/224.670da1e3.js +1 -0
  9. package/__mf/js/async/238.5c460cb2.js +1 -0
  10. package/__mf/js/async/292.4821b1b1.js +1 -0
  11. package/__mf/js/async/387.23da505f.js +1 -0
  12. package/__mf/js/async/409.12b6365d.js +1 -0
  13. package/__mf/js/async/488.2d364feb.js +1 -0
  14. package/__mf/js/async/533.f20b93c0.js +110 -0
  15. package/__mf/js/async/558.3b93d5ec.js +39 -0
  16. package/__mf/js/async/558.3b93d5ec.js.LICENSE.txt +21 -0
  17. package/__mf/js/async/62.1a6f8c05.js +1 -0
  18. package/__mf/js/async/651.bcb43163.js +1 -0
  19. package/__mf/js/async/{770.5431adef.js → 694.fe491393.js} +1 -1
  20. package/__mf/js/async/738.7d9e5092.js +1 -0
  21. package/__mf/js/async/740.fa3debdf.js +1 -0
  22. package/__mf/js/async/75.a3a29681.js +1 -0
  23. package/__mf/js/async/770.65ae427e.js +1 -0
  24. package/__mf/js/async/814.c33b5f31.js +2 -0
  25. package/__mf/js/async/814.c33b5f31.js.LICENSE.txt +24 -0
  26. package/__mf/js/async/832.0e397220.js +7 -0
  27. package/__mf/js/async/832.0e397220.js.LICENSE.txt +21 -0
  28. package/__mf/js/async/863.0e6501cd.js +2 -0
  29. package/__mf/js/async/897.f1628ec5.js +1 -0
  30. package/__mf/js/async/960.89291786.js +2 -0
  31. package/__mf/js/async/964.3f12c3f5.js +2 -0
  32. package/__mf/js/async/981.1c640ffc.js +2 -0
  33. package/__mf/js/async/__federation_expose_TracingGanttChart.3c44e08a.js +1 -0
  34. package/__mf/js/async/lib-router.ab6beae3.js +2 -0
  35. package/__mf/js/main.fb8fb582.js +5 -0
  36. package/lib/PanelActions.d.ts +9 -0
  37. package/lib/PanelActions.d.ts.map +1 -0
  38. package/lib/PanelActions.js +70 -0
  39. package/lib/PanelActions.js.map +1 -0
  40. package/lib/TracingGanttChart/DetailPane/Attributes.d.ts +15 -3
  41. package/lib/TracingGanttChart/DetailPane/Attributes.d.ts.map +1 -1
  42. package/lib/TracingGanttChart/DetailPane/Attributes.js +51 -18
  43. package/lib/TracingGanttChart/DetailPane/Attributes.js.map +1 -1
  44. package/lib/TracingGanttChart/DetailPane/DetailPane.d.ts +2 -2
  45. package/lib/TracingGanttChart/DetailPane/DetailPane.d.ts.map +1 -1
  46. package/lib/TracingGanttChart/DetailPane/DetailPane.js +17 -3
  47. package/lib/TracingGanttChart/DetailPane/DetailPane.js.map +1 -1
  48. package/lib/TracingGanttChart/DetailPane/SpanEvents.d.ts +2 -0
  49. package/lib/TracingGanttChart/DetailPane/SpanEvents.d.ts.map +1 -1
  50. package/lib/TracingGanttChart/DetailPane/SpanEvents.js +69 -23
  51. package/lib/TracingGanttChart/DetailPane/SpanEvents.js.map +1 -1
  52. package/lib/TracingGanttChart/DetailPane/SpanLinks.d.ts +9 -0
  53. package/lib/TracingGanttChart/DetailPane/SpanLinks.d.ts.map +1 -0
  54. package/lib/TracingGanttChart/DetailPane/SpanLinks.js +64 -0
  55. package/lib/TracingGanttChart/DetailPane/SpanLinks.js.map +1 -0
  56. package/lib/TracingGanttChart/GanttTable/GanttTable.d.ts +2 -1
  57. package/lib/TracingGanttChart/GanttTable/GanttTable.d.ts.map +1 -1
  58. package/lib/TracingGanttChart/GanttTable/GanttTable.js +15 -1
  59. package/lib/TracingGanttChart/GanttTable/GanttTable.js.map +1 -1
  60. package/lib/TracingGanttChart/GanttTable/GanttTableRow.d.ts +2 -1
  61. package/lib/TracingGanttChart/GanttTable/GanttTableRow.d.ts.map +1 -1
  62. package/lib/TracingGanttChart/GanttTable/GanttTableRow.js +2 -1
  63. package/lib/TracingGanttChart/GanttTable/GanttTableRow.js.map +1 -1
  64. package/lib/TracingGanttChart/GanttTable/SpanLinksButton.d.ts +8 -0
  65. package/lib/TracingGanttChart/GanttTable/SpanLinksButton.d.ts.map +1 -0
  66. package/lib/TracingGanttChart/GanttTable/SpanLinksButton.js +95 -0
  67. package/lib/TracingGanttChart/GanttTable/SpanLinksButton.js.map +1 -0
  68. package/lib/TracingGanttChart/GanttTable/SpanName.d.ts +2 -0
  69. package/lib/TracingGanttChart/GanttTable/SpanName.d.ts.map +1 -1
  70. package/lib/TracingGanttChart/GanttTable/SpanName.js +12 -1
  71. package/lib/TracingGanttChart/GanttTable/SpanName.js.map +1 -1
  72. package/lib/TracingGanttChart/MiniGanttChart/draw.d.ts.map +1 -1
  73. package/lib/TracingGanttChart/MiniGanttChart/draw.js +1 -8
  74. package/lib/TracingGanttChart/MiniGanttChart/draw.js.map +1 -1
  75. package/lib/TracingGanttChart/TracingGanttChart.d.ts +2 -3
  76. package/lib/TracingGanttChart/TracingGanttChart.d.ts.map +1 -1
  77. package/lib/TracingGanttChart/TracingGanttChart.js +4 -3
  78. package/lib/TracingGanttChart/TracingGanttChart.js.map +1 -1
  79. package/lib/TracingGanttChart/trace.d.ts +7 -0
  80. package/lib/TracingGanttChart/trace.d.ts.map +1 -1
  81. package/lib/TracingGanttChart/trace.js +13 -4
  82. package/lib/TracingGanttChart/trace.js.map +1 -1
  83. package/lib/TracingGanttChart.d.ts.map +1 -1
  84. package/lib/TracingGanttChart.js +7 -1
  85. package/lib/TracingGanttChart.js.map +1 -1
  86. package/lib/TracingGanttChartPanel.d.ts +1 -11
  87. package/lib/TracingGanttChartPanel.d.ts.map +1 -1
  88. package/lib/TracingGanttChartPanel.js +10 -2
  89. package/lib/TracingGanttChartPanel.js.map +1 -1
  90. package/lib/cjs/PanelActions.js +88 -0
  91. package/lib/cjs/TracingGanttChart/DetailPane/Attributes.js +56 -17
  92. package/lib/cjs/TracingGanttChart/DetailPane/DetailPane.js +17 -3
  93. package/lib/cjs/TracingGanttChart/DetailPane/SpanEvents.js +66 -20
  94. package/lib/cjs/TracingGanttChart/DetailPane/SpanLinks.js +72 -0
  95. package/lib/cjs/TracingGanttChart/GanttTable/GanttTable.js +15 -1
  96. package/lib/cjs/TracingGanttChart/GanttTable/GanttTableRow.js +2 -1
  97. package/lib/cjs/TracingGanttChart/GanttTable/SpanLinksButton.js +108 -0
  98. package/lib/cjs/TracingGanttChart/GanttTable/SpanName.js +12 -1
  99. package/lib/cjs/TracingGanttChart/MiniGanttChart/draw.js +1 -8
  100. package/lib/cjs/TracingGanttChart/TracingGanttChart.js +4 -3
  101. package/lib/cjs/TracingGanttChart/trace.js +13 -4
  102. package/lib/cjs/TracingGanttChart.js +7 -1
  103. package/lib/cjs/TracingGanttChartPanel.js +10 -2
  104. package/lib/cjs/gantt-chart-model.js +1 -1
  105. package/lib/gantt-chart-model.d.ts +31 -0
  106. package/lib/gantt-chart-model.d.ts.map +1 -1
  107. package/lib/gantt-chart-model.js +1 -1
  108. package/lib/gantt-chart-model.js.map +1 -1
  109. package/mf-manifest.json +86 -66
  110. package/mf-stats.json +100 -74
  111. package/package.json +7 -5
  112. package/__mf/js/788.5684e3ab.js +0 -5
  113. package/__mf/js/TracingGanttChart.77b94eb3.js +0 -5
  114. package/__mf/js/async/156.5a401ecb.js +0 -1
  115. package/__mf/js/async/173.6314a363.js +0 -2
  116. package/__mf/js/async/193.12ce9ab1.js +0 -44
  117. package/__mf/js/async/193.12ce9ab1.js.LICENSE.txt +0 -68
  118. package/__mf/js/async/377.59c252c4.js +0 -2
  119. package/__mf/js/async/511.b81ea373.js +0 -1
  120. package/__mf/js/async/620.1d1ce390.js +0 -2
  121. package/__mf/js/async/651.3ea371e5.js +0 -1
  122. package/__mf/js/async/694.4580ad20.js +0 -1
  123. package/__mf/js/async/740.babbb403.js +0 -1
  124. package/__mf/js/async/75.d81e6bbf.js +0 -1
  125. package/__mf/js/async/783.3c2c57f6.js +0 -110
  126. package/__mf/js/async/960.478a8f11.js +0 -2
  127. package/__mf/js/async/964.a98cab40.js +0 -2
  128. package/__mf/js/async/981.bc5132f8.js +0 -2
  129. package/__mf/js/async/__federation_expose_TracingGanttChart.7b5aeb33.js +0 -1
  130. package/__mf/js/main.9fe8ed9b.js +0 -1
  131. /package/__mf/js/async/{173.6314a363.js.LICENSE.txt → 173.66fc423e.js.LICENSE.txt} +0 -0
  132. /package/__mf/js/async/{783.3c2c57f6.js.LICENSE.txt → 533.f20b93c0.js.LICENSE.txt} +0 -0
  133. /package/__mf/js/async/{620.1d1ce390.js.LICENSE.txt → 863.0e6501cd.js.LICENSE.txt} +0 -0
  134. /package/__mf/js/async/{960.478a8f11.js.LICENSE.txt → 960.89291786.js.LICENSE.txt} +0 -0
  135. /package/__mf/js/async/{964.a98cab40.js.LICENSE.txt → 964.3f12c3f5.js.LICENSE.txt} +0 -0
  136. /package/__mf/js/async/{981.bc5132f8.js.LICENSE.txt → 981.1c640ffc.js.LICENSE.txt} +0 -0
  137. /package/__mf/js/async/{377.59c252c4.js.LICENSE.txt → lib-router.ab6beae3.js.LICENSE.txt} +0 -0
@@ -15,7 +15,7 @@ import { NoDataOverlay, TextOverlay, useChartsTheme } from '@perses-dev/componen
15
15
  import { Box } from '@mui/material';
16
16
  import { TracingGanttChart } from './TracingGanttChart/TracingGanttChart';
17
17
  export function TracingGanttChartPanel(props) {
18
- const { spec, queryResults, attributeLinks } = props;
18
+ const { spec, queryResults } = props;
19
19
  const chartsTheme = useChartsTheme();
20
20
  const contentPadding = chartsTheme.container.padding.default;
21
21
  if (queryResults.length > 1) {
@@ -29,6 +29,14 @@ export function TracingGanttChartPanel(props) {
29
29
  resource: "trace"
30
30
  });
31
31
  }
32
+ const pluginSpec = queryResults[0]?.definition.spec.plugin.spec;
33
+ const datasourceName = pluginSpec?.datasource?.name;
34
+ const customLinks = spec.links ? {
35
+ variables: {
36
+ datasourceName: datasourceName ?? ''
37
+ },
38
+ links: spec.links
39
+ } : undefined;
32
40
  return /*#__PURE__*/ _jsx(Box, {
33
41
  sx: {
34
42
  height: '100%',
@@ -36,7 +44,7 @@ export function TracingGanttChartPanel(props) {
36
44
  },
37
45
  children: /*#__PURE__*/ _jsx(TracingGanttChart, {
38
46
  options: spec,
39
- attributeLinks: attributeLinks,
47
+ customLinks: customLinks,
40
48
  trace: trace
41
49
  })
42
50
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/TracingGanttChartPanel.tsx"],"sourcesContent":["// Copyright 2024 The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { PanelProps } from '@perses-dev/plugin-system';\nimport { NoDataOverlay, TextOverlay, useChartsTheme } from '@perses-dev/components';\nimport { Box } from '@mui/material';\nimport { ReactElement } from 'react';\nimport { TraceData } from '@perses-dev/core';\nimport { TracingGanttChartOptions } from './gantt-chart-model';\nimport { TracingGanttChart } from './TracingGanttChart/TracingGanttChart';\nimport { AttributeLinks } from './TracingGanttChart/DetailPane/Attributes';\n\nexport interface TracingGanttChartPanelProps extends PanelProps<TracingGanttChartOptions, TraceData> {\n /**\n * Allows custom links for each attribute in the detail pane.\n * Example:\n * {\n * 'k8s.pod.name': (attrs) => `/my/console/namespace/${attrs['k8s.namespace.name']?.stringValue}/${attrs['k8s.pod.name']?.stringValue}/detail`\n * }\n */\n attributeLinks?: AttributeLinks;\n}\n\nexport function TracingGanttChartPanel(props: TracingGanttChartPanelProps): ReactElement {\n const { spec, queryResults, attributeLinks } = props;\n const chartsTheme = useChartsTheme();\n const contentPadding = chartsTheme.container.padding.default;\n\n if (queryResults.length > 1) {\n return <TextOverlay message=\"This panel does not support more than one query.\" />;\n }\n\n const trace = queryResults[0]?.data.trace;\n if (!trace) {\n return <NoDataOverlay resource=\"trace\" />;\n }\n\n return (\n <Box sx={{ height: '100%', padding: `${contentPadding}px` }}>\n <TracingGanttChart options={spec} attributeLinks={attributeLinks} trace={trace} />\n </Box>\n );\n}\n"],"names":["NoDataOverlay","TextOverlay","useChartsTheme","Box","TracingGanttChart","TracingGanttChartPanel","props","spec","queryResults","attributeLinks","chartsTheme","contentPadding","container","padding","default","length","message","trace","data","resource","sx","height","options"],"mappings":"AAAA,oCAAoC;AACpC,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,6CAA6C;AAC7C,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;;AAGjC,SAASA,aAAa,EAAEC,WAAW,EAAEC,cAAc,QAAQ,yBAAyB;AACpF,SAASC,GAAG,QAAQ,gBAAgB;AAIpC,SAASC,iBAAiB,QAAQ,wCAAwC;AAc1E,OAAO,SAASC,uBAAuBC,KAAkC;IACvE,MAAM,EAAEC,IAAI,EAAEC,YAAY,EAAEC,cAAc,EAAE,GAAGH;IAC/C,MAAMI,cAAcR;IACpB,MAAMS,iBAAiBD,YAAYE,SAAS,CAACC,OAAO,CAACC,OAAO;IAE5D,IAAIN,aAAaO,MAAM,GAAG,GAAG;QAC3B,qBAAO,KAACd;YAAYe,SAAQ;;IAC9B;IAEA,MAAMC,QAAQT,YAAY,CAAC,EAAE,EAAEU,KAAKD;IACpC,IAAI,CAACA,OAAO;QACV,qBAAO,KAACjB;YAAcmB,UAAS;;IACjC;IAEA,qBACE,KAAChB;QAAIiB,IAAI;YAAEC,QAAQ;YAAQR,SAAS,GAAGF,eAAe,EAAE,CAAC;QAAC;kBACxD,cAAA,KAACP;YAAkBkB,SAASf;YAAME,gBAAgBA;YAAgBQ,OAAOA;;;AAG/E"}
1
+ {"version":3,"sources":["../../src/TracingGanttChartPanel.tsx"],"sourcesContent":["// Copyright 2024 The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { PanelProps } from '@perses-dev/plugin-system';\nimport { NoDataOverlay, TextOverlay, useChartsTheme } from '@perses-dev/components';\nimport { Box } from '@mui/material';\nimport { ReactElement } from 'react';\nimport { TraceData } from '@perses-dev/core';\nimport { CustomLinks, TracingGanttChartOptions } from './gantt-chart-model';\nimport { TracingGanttChart } from './TracingGanttChart/TracingGanttChart';\n\nexport type TracingGanttChartPanelProps = PanelProps<TracingGanttChartOptions, TraceData>;\n\nexport function TracingGanttChartPanel(props: TracingGanttChartPanelProps): ReactElement {\n const { spec, queryResults } = props;\n const chartsTheme = useChartsTheme();\n const contentPadding = chartsTheme.container.padding.default;\n\n if (queryResults.length > 1) {\n return <TextOverlay message=\"This panel does not support more than one query.\" />;\n }\n\n const trace = queryResults[0]?.data.trace;\n if (!trace) {\n return <NoDataOverlay resource=\"trace\" />;\n }\n\n const pluginSpec = queryResults[0]?.definition.spec.plugin.spec as { datasource?: { name?: string } } | undefined;\n const datasourceName = pluginSpec?.datasource?.name;\n const customLinks: CustomLinks | undefined = spec.links\n ? {\n variables: {\n datasourceName: datasourceName ?? '',\n },\n links: spec.links,\n }\n : undefined;\n\n return (\n <Box sx={{ height: '100%', padding: `${contentPadding}px` }}>\n <TracingGanttChart options={spec} customLinks={customLinks} trace={trace} />\n </Box>\n );\n}\n"],"names":["NoDataOverlay","TextOverlay","useChartsTheme","Box","TracingGanttChart","TracingGanttChartPanel","props","spec","queryResults","chartsTheme","contentPadding","container","padding","default","length","message","trace","data","resource","pluginSpec","definition","plugin","datasourceName","datasource","name","customLinks","links","variables","undefined","sx","height","options"],"mappings":"AAAA,oCAAoC;AACpC,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,6CAA6C;AAC7C,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;;AAGjC,SAASA,aAAa,EAAEC,WAAW,EAAEC,cAAc,QAAQ,yBAAyB;AACpF,SAASC,GAAG,QAAQ,gBAAgB;AAIpC,SAASC,iBAAiB,QAAQ,wCAAwC;AAI1E,OAAO,SAASC,uBAAuBC,KAAkC;IACvE,MAAM,EAAEC,IAAI,EAAEC,YAAY,EAAE,GAAGF;IAC/B,MAAMG,cAAcP;IACpB,MAAMQ,iBAAiBD,YAAYE,SAAS,CAACC,OAAO,CAACC,OAAO;IAE5D,IAAIL,aAAaM,MAAM,GAAG,GAAG;QAC3B,qBAAO,KAACb;YAAYc,SAAQ;;IAC9B;IAEA,MAAMC,QAAQR,YAAY,CAAC,EAAE,EAAES,KAAKD;IACpC,IAAI,CAACA,OAAO;QACV,qBAAO,KAAChB;YAAckB,UAAS;;IACjC;IAEA,MAAMC,aAAaX,YAAY,CAAC,EAAE,EAAEY,WAAWb,KAAKc,OAAOd;IAC3D,MAAMe,iBAAiBH,YAAYI,YAAYC;IAC/C,MAAMC,cAAuClB,KAAKmB,KAAK,GACnD;QACEC,WAAW;YACTL,gBAAgBA,kBAAkB;QACpC;QACAI,OAAOnB,KAAKmB,KAAK;IACnB,IACAE;IAEJ,qBACE,KAACzB;QAAI0B,IAAI;YAAEC,QAAQ;YAAQlB,SAAS,GAAGF,eAAe,EAAE,CAAC;QAAC;kBACxD,cAAA,KAACN;YAAkB2B,SAASxB;YAAMkB,aAAaA;YAAaT,OAAOA;;;AAGzE"}
@@ -0,0 +1,88 @@
1
+ // Copyright 2025 The Perses Authors
2
+ // Licensed under the Apache License, Version 2.0 (the "License");
3
+ // you may not use this file except in compliance with the License.
4
+ // You may obtain a copy of the License at
5
+ //
6
+ // http://www.apache.org/licenses/LICENSE-2.0
7
+ //
8
+ // Unless required by applicable law or agreed to in writing, software
9
+ // distributed under the License is distributed on an "AS IS" BASIS,
10
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ // See the License for the specific language governing permissions and
12
+ // limitations under the License.
13
+ "use strict";
14
+ Object.defineProperty(exports, "__esModule", {
15
+ value: true
16
+ });
17
+ function _export(target, all) {
18
+ for(var name in all)Object.defineProperty(target, name, {
19
+ enumerable: true,
20
+ get: all[name]
21
+ });
22
+ }
23
+ _export(exports, {
24
+ DownloadTraceAction: function() {
25
+ return DownloadTraceAction;
26
+ },
27
+ getFilename: function() {
28
+ return getFilename;
29
+ }
30
+ });
31
+ const _jsxruntime = require("react/jsx-runtime");
32
+ const _components = require("@perses-dev/components");
33
+ const _DownloadOutline = /*#__PURE__*/ _interop_require_default(require("mdi-material-ui/DownloadOutline"));
34
+ const _react = require("react");
35
+ const _dashboards = require("@perses-dev/dashboards");
36
+ function _interop_require_default(obj) {
37
+ return obj && obj.__esModule ? obj : {
38
+ default: obj
39
+ };
40
+ }
41
+ function DownloadTraceAction(props) {
42
+ const { queryResults } = props;
43
+ const trace = queryResults[0]?.data?.trace;
44
+ const handleClick = (0, _react.useCallback)(()=>{
45
+ if (!trace) return;
46
+ const data = JSON.stringify(trace, null, 2);
47
+ const filename = getFilename(trace);
48
+ downloadFile(filename, 'application/json', data);
49
+ }, [
50
+ trace
51
+ ]);
52
+ if (!trace) {
53
+ return;
54
+ }
55
+ return /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.InfoTooltip, {
56
+ description: "download OTLP/JSON trace",
57
+ children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_dashboards.HeaderIconButton, {
58
+ "aria-label": "download OTLP/JSON trace",
59
+ size: "small",
60
+ onClick: handleClick,
61
+ children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_DownloadOutline.default, {
62
+ fontSize: "inherit"
63
+ })
64
+ })
65
+ });
66
+ }
67
+ function getFilename(trace) {
68
+ for (const resourceSpan of trace.resourceSpans){
69
+ for (const scopeSpan of resourceSpan.scopeSpans){
70
+ for (const span of scopeSpan.spans){
71
+ return `${span.traceId}.json`;
72
+ }
73
+ }
74
+ }
75
+ return 'trace.json';
76
+ }
77
+ function downloadFile(filename, type, data) {
78
+ const url = URL.createObjectURL(new Blob([
79
+ data
80
+ ], {
81
+ type
82
+ }));
83
+ const link = document.createElement('a');
84
+ link.download = filename;
85
+ link.href = url;
86
+ link.click();
87
+ URL.revokeObjectURL(url);
88
+ }
@@ -21,6 +21,12 @@ function _export(target, all) {
21
21
  });
22
22
  }
23
23
  _export(exports, {
24
+ AttributeItem: function() {
25
+ return AttributeItem;
26
+ },
27
+ AttributeItems: function() {
28
+ return AttributeItems;
29
+ },
24
30
  AttributeList: function() {
25
31
  return AttributeList;
26
32
  },
@@ -31,10 +37,10 @@ _export(exports, {
31
37
  const _jsxruntime = require("react/jsx-runtime");
32
38
  const _react = require("react");
33
39
  const _material = require("@mui/material");
34
- const _reactrouterdom = require("react-router-dom");
40
+ const _pluginsystem = require("@perses-dev/plugin-system");
35
41
  const _utils = require("../utils");
36
42
  function TraceAttributes(props) {
37
- const { trace, span, attributeLinks } = props;
43
+ const { customLinks, trace, span } = props;
38
44
  return /*#__PURE__*/ (0, _jsxruntime.jsxs)(_jsxruntime.Fragment, {
39
45
  children: [
40
46
  /*#__PURE__*/ (0, _jsxruntime.jsxs)(_material.List, {
@@ -57,44 +63,77 @@ function TraceAttributes(props) {
57
63
  span.attributes.length > 0 && /*#__PURE__*/ (0, _jsxruntime.jsxs)(_jsxruntime.Fragment, {
58
64
  children: [
59
65
  /*#__PURE__*/ (0, _jsxruntime.jsx)(AttributeList, {
60
- attributeLinks: attributeLinks,
61
- attributes: span.attributes
66
+ customLinks: customLinks,
67
+ attributes: span.attributes.toSorted((a, b)=>a.key.localeCompare(b.key))
62
68
  }),
63
69
  /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Divider, {})
64
70
  ]
65
71
  }),
66
72
  /*#__PURE__*/ (0, _jsxruntime.jsx)(AttributeList, {
67
- attributeLinks: attributeLinks,
68
- attributes: span.resource.attributes
73
+ customLinks: customLinks,
74
+ attributes: span.resource.attributes.toSorted((a, b)=>a.key.localeCompare(b.key))
69
75
  })
70
76
  ]
71
77
  });
72
78
  }
73
79
  function AttributeList(props) {
74
- const { attributeLinks, attributes } = props;
75
- const attributesMap = (0, _react.useMemo)(()=>Object.fromEntries(attributes.map((attr)=>[
76
- attr.key,
77
- attr.value
78
- ])), [
80
+ const { customLinks, attributes } = props;
81
+ return /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.List, {
82
+ children: /*#__PURE__*/ (0, _jsxruntime.jsx)(AttributeItems, {
83
+ customLinks: customLinks,
84
+ attributes: attributes
85
+ })
86
+ });
87
+ }
88
+ function AttributeItems(props) {
89
+ const { customLinks, attributes } = props;
90
+ const variableValues = (0, _pluginsystem.useAllVariableValues)();
91
+ // turn array into map for fast access
92
+ const attributeLinks = (0, _react.useMemo)(()=>{
93
+ const attrs = (customLinks?.links.attributes ?? []).map((a)=>[
94
+ a.name,
95
+ a.link
96
+ ]);
97
+ return Object.fromEntries(attrs);
98
+ }, [
99
+ customLinks
100
+ ]);
101
+ // some links require access to other attributes, for example a pod link "/namespace/${k8s_namespace_name}/pod/${k8s_pod_name}"
102
+ const extraVariables = (0, _react.useMemo)(()=>{
103
+ // replace dot with underscore in attribute name, because dot is not allowed in variable names
104
+ const stringAttrs = attributes.map((attr)=>[
105
+ attr.key.replaceAll('.', '_'),
106
+ renderAttributeValue(attr.value)
107
+ ]);
108
+ return {
109
+ ...customLinks?.variables,
110
+ ...Object.fromEntries(stringAttrs)
111
+ };
112
+ }, [
113
+ customLinks,
79
114
  attributes
80
115
  ]);
81
- return /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.List, {
82
- children: attributes.sort((a, b)=>a.key.localeCompare(b.key)).map((attribute, i)=>/*#__PURE__*/ (0, _jsxruntime.jsx)(AttributeItem, {
116
+ return /*#__PURE__*/ (0, _jsxruntime.jsx)(_jsxruntime.Fragment, {
117
+ children: attributes.map((attribute, i)=>/*#__PURE__*/ (0, _jsxruntime.jsx)(AttributeItem, {
83
118
  name: attribute.key,
84
119
  value: renderAttributeValue(attribute.value),
85
- link: attributeLinks?.[attribute.key]?.(attributesMap)
120
+ link: attributeLinks[attribute.key] ? (0, _pluginsystem.replaceVariablesInString)(attributeLinks[attribute.key], variableValues, extraVariables) : undefined
86
121
  }, i))
87
122
  });
88
123
  }
89
124
  function AttributeItem(props) {
90
125
  const { name, value, link } = props;
91
- const valueComponent = link ? /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Link, {
92
- component: _reactrouterdom.Link,
126
+ const { RouterComponent } = (0, _pluginsystem.useRouterContext)();
127
+ const valueComponent = RouterComponent && link ? /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Link, {
128
+ component: RouterComponent,
93
129
  to: link,
94
130
  children: value
95
131
  }) : value;
96
132
  return /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.ListItem, {
97
- disablePadding: true,
133
+ sx: {
134
+ px: 1,
135
+ py: 0
136
+ },
98
137
  children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.ListItemText, {
99
138
  primary: name,
100
139
  secondary: valueComponent,
@@ -26,19 +26,24 @@ const _react = require("react");
26
26
  const _Close = /*#__PURE__*/ _interop_require_default(require("mdi-material-ui/Close"));
27
27
  const _Attributes = require("./Attributes");
28
28
  const _SpanEvents = require("./SpanEvents");
29
+ const _SpanLinks = require("./SpanLinks");
29
30
  function _interop_require_default(obj) {
30
31
  return obj && obj.__esModule ? obj : {
31
32
  default: obj
32
33
  };
33
34
  }
34
35
  function DetailPane(props) {
35
- const { attributeLinks, trace, span, onCloseBtnClick } = props;
36
+ const { customLinks, trace, span, onCloseBtnClick } = props;
36
37
  const [tab, setTab] = (0, _react.useState)('attributes');
37
38
  // if the events tab is selected, and then a span without events is clicked,
38
39
  // we need to switch the current selected tab back to the attributes tab.
39
40
  if (tab === 'events' && span.events.length === 0) {
40
41
  setTab('attributes');
41
42
  }
43
+ // same as above, but for span links
44
+ if (tab === 'links' && span.links.length === 0) {
45
+ setTab('attributes');
46
+ }
42
47
  return /*#__PURE__*/ (0, _jsxruntime.jsxs)(_material.Box, {
43
48
  children: [
44
49
  /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.IconButton, {
@@ -80,18 +85,27 @@ function DetailPane(props) {
80
85
  span.events.length > 0 && /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Tab, {
81
86
  value: "events",
82
87
  label: "Events"
88
+ }),
89
+ span.links.length > 0 && /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Tab, {
90
+ value: "links",
91
+ label: "Links"
83
92
  })
84
93
  ]
85
94
  })
86
95
  }),
87
96
  tab === 'attributes' && /*#__PURE__*/ (0, _jsxruntime.jsx)(_Attributes.TraceAttributes, {
97
+ customLinks: customLinks,
88
98
  trace: trace,
89
- span: span,
90
- attributeLinks: attributeLinks
99
+ span: span
91
100
  }),
92
101
  tab === 'events' && /*#__PURE__*/ (0, _jsxruntime.jsx)(_SpanEvents.SpanEventList, {
102
+ customLinks: customLinks,
93
103
  trace: trace,
94
104
  span: span
105
+ }),
106
+ tab === 'links' && /*#__PURE__*/ (0, _jsxruntime.jsx)(_SpanLinks.SpanLinkList, {
107
+ customLinks: customLinks,
108
+ span: span
95
109
  })
96
110
  ]
97
111
  });
@@ -22,6 +22,8 @@ Object.defineProperty(exports, "SpanEventList", {
22
22
  });
23
23
  const _jsxruntime = require("react/jsx-runtime");
24
24
  const _material = require("@mui/material");
25
+ const _react = require("react");
26
+ const _ChevronUp = /*#__PURE__*/ _interop_require_default(require("mdi-material-ui/ChevronUp"));
25
27
  const _ChevronDown = /*#__PURE__*/ _interop_require_default(require("mdi-material-ui/ChevronDown"));
26
28
  const _utils = require("../utils");
27
29
  const _Attributes = require("./Attributes");
@@ -31,36 +33,80 @@ function _interop_require_default(obj) {
31
33
  };
32
34
  }
33
35
  function SpanEventList(props) {
34
- const { trace, span } = props;
36
+ const { customLinks, trace, span } = props;
35
37
  return /*#__PURE__*/ (0, _jsxruntime.jsx)(_jsxruntime.Fragment, {
36
- children: span.events.sort((a, b)=>a.timeUnixMs - b.timeUnixMs).map((event, i)=>/*#__PURE__*/ (0, _jsxruntime.jsx)(SpanEventItem, {
37
- trace: trace,
38
- event: event
38
+ children: span.events.sort((a, b)=>a.timeUnixMs - b.timeUnixMs).map((event, i)=>/*#__PURE__*/ (0, _jsxruntime.jsxs)(_react.Fragment, {
39
+ children: [
40
+ i > 0 && /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Divider, {}),
41
+ /*#__PURE__*/ (0, _jsxruntime.jsx)(SpanEventItem, {
42
+ customLinks: customLinks,
43
+ trace: trace,
44
+ event: event
45
+ })
46
+ ]
39
47
  }, i))
40
48
  });
41
49
  }
42
50
  function SpanEventItem(props) {
43
- const { trace, event } = props;
51
+ const { customLinks, trace, event } = props;
44
52
  const relativeTime = event.timeUnixMs - trace.startTimeUnixMs;
45
- return /*#__PURE__*/ (0, _jsxruntime.jsxs)(_material.Accordion, {
46
- disableGutters: true,
53
+ const [open, setOpen] = (0, _react.useState)(false);
54
+ const handleClick = ()=>{
55
+ setOpen(!open);
56
+ };
57
+ return /*#__PURE__*/ (0, _jsxruntime.jsxs)(_material.List, {
47
58
  children: [
48
- /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.AccordionSummary, {
49
- expandIcon: /*#__PURE__*/ (0, _jsxruntime.jsx)(_ChevronDown.default, {}),
50
- children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Typography, {
51
- children: (0, _utils.formatDuration)(relativeTime)
52
- })
53
- }),
54
- /*#__PURE__*/ (0, _jsxruntime.jsxs)(_material.AccordionDetails, {
59
+ /*#__PURE__*/ (0, _jsxruntime.jsxs)(_material.ListItemButton, {
60
+ onClick: handleClick,
61
+ sx: {
62
+ px: 1
63
+ },
55
64
  children: [
56
- /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Typography, {
57
- variant: "subtitle1",
58
- children: event.name
65
+ /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.ListItemText, {
66
+ primary: /*#__PURE__*/ (0, _jsxruntime.jsxs)(_jsxruntime.Fragment, {
67
+ children: [
68
+ /*#__PURE__*/ (0, _jsxruntime.jsxs)("strong", {
69
+ children: [
70
+ (0, _utils.formatDuration)(relativeTime),
71
+ ":"
72
+ ]
73
+ }),
74
+ " ",
75
+ event.name
76
+ ]
77
+ }),
78
+ slotProps: {
79
+ primary: {
80
+ noWrap: true
81
+ }
82
+ }
59
83
  }),
60
- /*#__PURE__*/ (0, _jsxruntime.jsx)(_Attributes.AttributeList, {
61
- attributes: event.attributes
62
- })
84
+ open ? /*#__PURE__*/ (0, _jsxruntime.jsx)(_ChevronUp.default, {}) : /*#__PURE__*/ (0, _jsxruntime.jsx)(_ChevronDown.default, {})
63
85
  ]
86
+ }),
87
+ /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Collapse, {
88
+ in: open,
89
+ timeout: "auto",
90
+ unmountOnExit: true,
91
+ children: /*#__PURE__*/ (0, _jsxruntime.jsxs)(_material.List, {
92
+ sx: {
93
+ px: 1
94
+ },
95
+ children: [
96
+ /*#__PURE__*/ (0, _jsxruntime.jsx)(_Attributes.AttributeItem, {
97
+ name: "name",
98
+ value: event.name
99
+ }),
100
+ /*#__PURE__*/ (0, _jsxruntime.jsx)(_Attributes.AttributeItem, {
101
+ name: "time",
102
+ value: (0, _utils.formatDuration)(relativeTime)
103
+ }),
104
+ /*#__PURE__*/ (0, _jsxruntime.jsx)(_Attributes.AttributeItems, {
105
+ customLinks: customLinks,
106
+ attributes: event.attributes
107
+ })
108
+ ]
109
+ })
64
110
  })
65
111
  ]
66
112
  });
@@ -0,0 +1,72 @@
1
+ // Copyright 2025 The Perses Authors
2
+ // Licensed under the Apache License, Version 2.0 (the "License");
3
+ // you may not use this file except in compliance with the License.
4
+ // You may obtain a copy of the License at
5
+ //
6
+ // http://www.apache.org/licenses/LICENSE-2.0
7
+ //
8
+ // Unless required by applicable law or agreed to in writing, software
9
+ // distributed under the License is distributed on an "AS IS" BASIS,
10
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ // See the License for the specific language governing permissions and
12
+ // limitations under the License.
13
+ "use strict";
14
+ Object.defineProperty(exports, "__esModule", {
15
+ value: true
16
+ });
17
+ Object.defineProperty(exports, "SpanLinkList", {
18
+ enumerable: true,
19
+ get: function() {
20
+ return SpanLinkList;
21
+ }
22
+ });
23
+ const _jsxruntime = require("react/jsx-runtime");
24
+ const _material = require("@mui/material");
25
+ const _react = require("react");
26
+ const _pluginsystem = require("@perses-dev/plugin-system");
27
+ const _Attributes = require("./Attributes");
28
+ function SpanLinkList(props) {
29
+ const { customLinks, span } = props;
30
+ return /*#__PURE__*/ (0, _jsxruntime.jsx)(_jsxruntime.Fragment, {
31
+ children: span.links.map((link, i)=>/*#__PURE__*/ (0, _jsxruntime.jsxs)(_react.Fragment, {
32
+ children: [
33
+ i > 0 && /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Divider, {}),
34
+ /*#__PURE__*/ (0, _jsxruntime.jsx)(SpanLinkItem, {
35
+ link: link,
36
+ customLinks: customLinks
37
+ })
38
+ ]
39
+ }, i))
40
+ });
41
+ }
42
+ function SpanLinkItem(props) {
43
+ const { customLinks, link } = props;
44
+ const variableValues = (0, _pluginsystem.useAllVariableValues)();
45
+ const traceLink = customLinks?.links.trace ? (0, _pluginsystem.replaceVariablesInString)(customLinks.links.trace, variableValues, {
46
+ ...customLinks?.variables,
47
+ traceId: link.traceId
48
+ }) : undefined;
49
+ const spanLink = customLinks?.links.span ? (0, _pluginsystem.replaceVariablesInString)(customLinks.links.span, variableValues, {
50
+ ...customLinks?.variables,
51
+ traceId: link.traceId,
52
+ spanId: link.spanId
53
+ }) : undefined;
54
+ return /*#__PURE__*/ (0, _jsxruntime.jsxs)(_material.List, {
55
+ children: [
56
+ /*#__PURE__*/ (0, _jsxruntime.jsx)(_Attributes.AttributeItem, {
57
+ name: "trace ID",
58
+ value: link.traceId,
59
+ link: traceLink
60
+ }),
61
+ /*#__PURE__*/ (0, _jsxruntime.jsx)(_Attributes.AttributeItem, {
62
+ name: "span ID",
63
+ value: link.spanId,
64
+ link: spanLink
65
+ }),
66
+ /*#__PURE__*/ (0, _jsxruntime.jsx)(_Attributes.AttributeItems, {
67
+ customLinks: customLinks,
68
+ attributes: link.attributes
69
+ })
70
+ ]
71
+ });
72
+ }
@@ -29,7 +29,7 @@ const _GanttTableRow = require("./GanttTableRow");
29
29
  const _GanttTableHeader = require("./GanttTableHeader");
30
30
  const _ResizableDivider = require("./ResizableDivider");
31
31
  function GanttTable(props) {
32
- const { options, trace, viewport, selectedSpan, onSpanClick } = props;
32
+ const { options, customLinks, trace, viewport, selectedSpan, onSpanClick } = props;
33
33
  const { collapsedSpans, setVisibleSpans } = (0, _GanttTableProvider.useGanttTableContext)();
34
34
  const [nameColumnWidth, setNameColumnWidth] = (0, _react.useState)(0.25);
35
35
  const tableRef = (0, _react.useRef)(null);
@@ -44,6 +44,18 @@ function GanttTable(props) {
44
44
  trace.rootSpans,
45
45
  collapsedSpans
46
46
  ]);
47
+ const selectedSpanIndex = (0, _react.useMemo)(()=>{
48
+ if (!selectedSpan) return undefined;
49
+ for(let i = 0; i < rows.length; i++){
50
+ if (rows[i]?.spanId === selectedSpan.spanId) {
51
+ return i;
52
+ }
53
+ }
54
+ return undefined;
55
+ }, [
56
+ rows,
57
+ selectedSpan
58
+ ]);
47
59
  const divider = /*#__PURE__*/ (0, _jsxruntime.jsx)(_ResizableDivider.ResizableDivider, {
48
60
  parentRef: tableRef,
49
61
  onMove: setNameColumnWidth
@@ -74,8 +86,10 @@ function GanttTable(props) {
74
86
  }),
75
87
  /*#__PURE__*/ (0, _jsxruntime.jsx)(_reactvirtuoso.Virtuoso, {
76
88
  data: rows,
89
+ initialTopMostItemIndex: selectedSpanIndex ?? 0,
77
90
  itemContent: (_, span)=>/*#__PURE__*/ (0, _jsxruntime.jsx)(_GanttTableRow.GanttTableRow, {
78
91
  options: options,
92
+ customLinks: customLinks,
79
93
  span: span,
80
94
  viewport: viewport,
81
95
  selected: span === selectedSpan,
@@ -27,7 +27,7 @@ const _utils = require("../utils");
27
27
  const _SpanName = require("./SpanName");
28
28
  const _SpanDuration = require("./SpanDuration");
29
29
  const GanttTableRow = /*#__PURE__*/ (0, _react.memo)(function GanttTableRow(props) {
30
- const { options, span, viewport, selected, nameColumnWidth, divider, onClick } = props;
30
+ const { options, customLinks, span, viewport, selected, nameColumnWidth, divider, onClick } = props;
31
31
  const theme = (0, _material.useTheme)();
32
32
  const handleOnClick = ()=>{
33
33
  // ignore event if triggered by selecting text
@@ -42,6 +42,7 @@ const GanttTableRow = /*#__PURE__*/ (0, _react.memo)(function GanttTableRow(prop
42
42
  onClick: handleOnClick,
43
43
  children: [
44
44
  /*#__PURE__*/ (0, _jsxruntime.jsx)(_SpanName.SpanName, {
45
+ customLinks: customLinks,
45
46
  span: span,
46
47
  nameColumnWidth: nameColumnWidth
47
48
  }),
@@ -0,0 +1,108 @@
1
+ // Copyright 2025 The Perses Authors
2
+ // Licensed under the Apache License, Version 2.0 (the "License");
3
+ // you may not use this file except in compliance with the License.
4
+ // You may obtain a copy of the License at
5
+ //
6
+ // http://www.apache.org/licenses/LICENSE-2.0
7
+ //
8
+ // Unless required by applicable law or agreed to in writing, software
9
+ // distributed under the License is distributed on an "AS IS" BASIS,
10
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ // See the License for the specific language governing permissions and
12
+ // limitations under the License.
13
+ "use strict";
14
+ Object.defineProperty(exports, "__esModule", {
15
+ value: true
16
+ });
17
+ Object.defineProperty(exports, "SpanLinksButton", {
18
+ enumerable: true,
19
+ get: function() {
20
+ return SpanLinksButton;
21
+ }
22
+ });
23
+ const _jsxruntime = require("react/jsx-runtime");
24
+ const _material = require("@mui/material");
25
+ const _react = require("react");
26
+ const _Launch = /*#__PURE__*/ _interop_require_default(require("mdi-material-ui/Launch"));
27
+ const _components = require("@perses-dev/components");
28
+ const _pluginsystem = require("@perses-dev/plugin-system");
29
+ function _interop_require_default(obj) {
30
+ return obj && obj.__esModule ? obj : {
31
+ default: obj
32
+ };
33
+ }
34
+ function SpanLinksButton(props) {
35
+ const { customLinks, span } = props;
36
+ const variableValues = (0, _pluginsystem.useAllVariableValues)();
37
+ const { RouterComponent } = (0, _pluginsystem.useRouterContext)();
38
+ const [anchorEl, setAnchorEl] = (0, _react.useState)(null);
39
+ const isOpen = Boolean(anchorEl);
40
+ if (!RouterComponent || !customLinks.links.span) {
41
+ return;
42
+ }
43
+ // if there is a single span link, render the button directly without a menu
44
+ if (span.links.length == 1 && span.links[0]) {
45
+ const link = span.links[0];
46
+ return /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.InfoTooltip, {
47
+ description: "open linked span",
48
+ children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.IconButton, {
49
+ size: "small",
50
+ component: RouterComponent,
51
+ to: (0, _pluginsystem.replaceVariablesInString)(customLinks.links.span, variableValues, {
52
+ ...customLinks.variables,
53
+ traceId: link.traceId,
54
+ spanId: link.spanId
55
+ }),
56
+ children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_Launch.default, {
57
+ fontSize: "inherit"
58
+ })
59
+ })
60
+ });
61
+ }
62
+ const handleOpenMenu = (event)=>{
63
+ // do not propagate onClick event to the table row (otherwise, the detail pane would open)
64
+ event.stopPropagation();
65
+ setAnchorEl(event.currentTarget);
66
+ };
67
+ const handleClose = (event)=>{
68
+ // Closing the menu, i.e. clicking on the fullscreen transparent MUI backdrop element, does trigger a click on the table row (which opens the detail pane).
69
+ // Therefore, stop propagating this event
70
+ event.stopPropagation();
71
+ setAnchorEl(null);
72
+ };
73
+ return /*#__PURE__*/ (0, _jsxruntime.jsxs)(_jsxruntime.Fragment, {
74
+ children: [
75
+ /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.InfoTooltip, {
76
+ description: `${span.links.length} linked spans`,
77
+ children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.IconButton, {
78
+ "aria-label": "span links",
79
+ "aria-haspopup": "true",
80
+ "aria-expanded": isOpen ? 'true' : undefined,
81
+ size: "small",
82
+ onClick: handleOpenMenu,
83
+ children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_Launch.default, {
84
+ fontSize: "inherit"
85
+ })
86
+ })
87
+ }),
88
+ /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Menu, {
89
+ anchorEl: anchorEl,
90
+ open: isOpen,
91
+ onClose: handleClose,
92
+ children: span.links.map((link)=>/*#__PURE__*/ (0, _jsxruntime.jsxs)(_material.MenuItem, {
93
+ component: RouterComponent,
94
+ onClick: handleClose,
95
+ to: (0, _pluginsystem.replaceVariablesInString)(customLinks.links.span, variableValues, {
96
+ ...customLinks.variables,
97
+ traceId: link.traceId,
98
+ spanId: link.spanId
99
+ }),
100
+ children: [
101
+ "Open linked span ",
102
+ link.spanId
103
+ ]
104
+ }, link.spanId))
105
+ })
106
+ ]
107
+ });
108
+ }