@perses-dev/timeseries-chart-plugin 0.9.0 → 0.10.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 (107) hide show
  1. package/__mf/js/TimeSeriesChart.d3742b3b.js +5 -0
  2. package/__mf/js/async/109.bf4f02fe.js +73 -0
  3. package/__mf/js/async/133.c48c8cc8.js +110 -0
  4. package/__mf/js/async/{879.24def15a.js.LICENSE.txt → 133.c48c8cc8.js.LICENSE.txt} +28 -0
  5. package/__mf/js/async/173.58a1dc61.js +2 -0
  6. package/__mf/js/async/214.37696543.js +1 -0
  7. package/__mf/js/async/224.2d3ce51f.js +1 -0
  8. package/__mf/js/async/238.767e5398.js +1 -0
  9. package/__mf/js/async/292.9efc6a73.js +1 -0
  10. package/__mf/js/async/409.97dde548.js +1 -0
  11. package/__mf/js/async/476.23a59a72.js +1 -0
  12. package/__mf/js/async/488.031fc875.js +1 -0
  13. package/__mf/js/async/53.8edfe937.js +2 -0
  14. package/__mf/js/async/547.bb4f1e58.js +7 -0
  15. package/__mf/js/async/580.5f4b0dbd.js +38 -0
  16. package/__mf/js/async/613.20f15bb7.js +1 -0
  17. package/__mf/js/async/62.f24fce0a.js +1 -0
  18. package/__mf/js/async/651.e0c9e225.js +1 -0
  19. package/__mf/js/async/686.0cd9a75c.js +1 -0
  20. package/__mf/js/async/694.ebf24a00.js +1 -0
  21. package/__mf/js/async/738.c37f7bca.js +1 -0
  22. package/__mf/js/async/740.f0e8d499.js +1 -0
  23. package/__mf/js/async/75.26ec5bee.js +1 -0
  24. package/__mf/js/async/770.e129dd07.js +1 -0
  25. package/__mf/js/async/797.72ff552e.js +2 -0
  26. package/__mf/js/async/863.f147d2ba.js +2 -0
  27. package/__mf/js/async/960.cd399075.js +2 -0
  28. package/__mf/js/async/964.719c530c.js +2 -0
  29. package/__mf/js/async/981.e360e7df.js +2 -0
  30. package/__mf/js/async/__federation_expose_TimeSeriesChart.f20a0aca.js +3 -0
  31. package/__mf/js/async/lib-router.25a1f509.js +2 -0
  32. package/__mf/js/main.2c598209.js +5 -0
  33. package/lib/CSVExportUtils.d.ts +39 -0
  34. package/lib/CSVExportUtils.d.ts.map +1 -0
  35. package/lib/CSVExportUtils.js +212 -0
  36. package/lib/CSVExportUtils.js.map +1 -0
  37. package/lib/TimeSeriesChart.d.ts +0 -3
  38. package/lib/TimeSeriesChart.d.ts.map +1 -1
  39. package/lib/TimeSeriesChart.js +9 -4
  40. package/lib/TimeSeriesChart.js.map +1 -1
  41. package/lib/TimeSeriesChartBase.d.ts.map +1 -1
  42. package/lib/TimeSeriesChartBase.js +2 -2
  43. package/lib/TimeSeriesChartBase.js.map +1 -1
  44. package/lib/TimeSeriesChartOptionsEditorSettings.js +1 -0
  45. package/lib/TimeSeriesChartOptionsEditorSettings.js.map +1 -1
  46. package/lib/TimeSeriesChartPanel.d.ts.map +1 -1
  47. package/lib/TimeSeriesChartPanel.js.map +1 -1
  48. package/lib/TimeSeriesExportAction.d.ts +4 -0
  49. package/lib/TimeSeriesExportAction.d.ts.map +1 -0
  50. package/lib/TimeSeriesExportAction.js +69 -0
  51. package/lib/TimeSeriesExportAction.js.map +1 -0
  52. package/lib/cjs/CSVExportUtils.js +246 -0
  53. package/lib/cjs/TimeSeriesChart.js +8 -1
  54. package/lib/cjs/TimeSeriesChartBase.js +2 -2
  55. package/lib/cjs/TimeSeriesChartOptionsEditorSettings.js +1 -0
  56. package/lib/cjs/TimeSeriesExportAction.js +123 -0
  57. package/lib/cjs/index.js +1 -0
  58. package/lib/index.d.ts +1 -0
  59. package/lib/index.d.ts.map +1 -1
  60. package/lib/index.js +1 -0
  61. package/lib/index.js.map +1 -1
  62. package/mf-manifest.json +41 -90
  63. package/mf-stats.json +41 -90
  64. package/package.json +12 -4
  65. package/__mf/js/983.b0368f8f.js +0 -5
  66. package/__mf/js/TimeSeriesChart.33363c77.js +0 -5
  67. package/__mf/js/async/171.598de6a9.js +0 -7
  68. package/__mf/js/async/173.f6f7e45b.js +0 -2
  69. package/__mf/js/async/214.2d4431c6.js +0 -1
  70. package/__mf/js/async/223.def4d0a9.js +0 -1
  71. package/__mf/js/async/224.ce414ffb.js +0 -1
  72. package/__mf/js/async/238.625b8a48.js +0 -1
  73. package/__mf/js/async/281.a2a87c37.js +0 -2
  74. package/__mf/js/async/292.311e6eb0.js +0 -1
  75. package/__mf/js/async/359.18a264e7.js +0 -2
  76. package/__mf/js/async/409.b4cabab7.js +0 -1
  77. package/__mf/js/async/476.45fca8d3.js +0 -1
  78. package/__mf/js/async/488.0d0b1a91.js +0 -1
  79. package/__mf/js/async/620.d6f96402.js +0 -2
  80. package/__mf/js/async/651.80087530.js +0 -1
  81. package/__mf/js/async/656.d43503a5.js +0 -1
  82. package/__mf/js/async/694.27c70ab1.js +0 -1
  83. package/__mf/js/async/738.0a12bb44.js +0 -1
  84. package/__mf/js/async/740.67107c3c.js +0 -1
  85. package/__mf/js/async/75.5952779d.js +0 -1
  86. package/__mf/js/async/755.f76e3538.js +0 -38
  87. package/__mf/js/async/770.78a741ab.js +0 -1
  88. package/__mf/js/async/780.3fa36115.js +0 -110
  89. package/__mf/js/async/780.3fa36115.js.LICENSE.txt +0 -27
  90. package/__mf/js/async/845.6d99c354.js +0 -73
  91. package/__mf/js/async/879.24def15a.js +0 -2
  92. package/__mf/js/async/960.3047096d.js +0 -2
  93. package/__mf/js/async/964.6dfbf211.js +0 -2
  94. package/__mf/js/async/981.77f901c0.js +0 -2
  95. package/__mf/js/async/__federation_expose_TimeSeriesChart.1e16af77.js +0 -1
  96. package/__mf/js/async/lib-router.098fc614.js +0 -2
  97. package/__mf/js/main.beef92ec.js +0 -1
  98. /package/__mf/js/async/{845.6d99c354.js.LICENSE.txt → 109.bf4f02fe.js.LICENSE.txt} +0 -0
  99. /package/__mf/js/async/{173.f6f7e45b.js.LICENSE.txt → 173.58a1dc61.js.LICENSE.txt} +0 -0
  100. /package/__mf/js/async/{359.18a264e7.js.LICENSE.txt → 53.8edfe937.js.LICENSE.txt} +0 -0
  101. /package/__mf/js/async/{171.598de6a9.js.LICENSE.txt → 547.bb4f1e58.js.LICENSE.txt} +0 -0
  102. /package/__mf/js/async/{281.a2a87c37.js.LICENSE.txt → 797.72ff552e.js.LICENSE.txt} +0 -0
  103. /package/__mf/js/async/{620.d6f96402.js.LICENSE.txt → 863.f147d2ba.js.LICENSE.txt} +0 -0
  104. /package/__mf/js/async/{960.3047096d.js.LICENSE.txt → 960.cd399075.js.LICENSE.txt} +0 -0
  105. /package/__mf/js/async/{964.6dfbf211.js.LICENSE.txt → 964.719c530c.js.LICENSE.txt} +0 -0
  106. /package/__mf/js/async/{981.77f901c0.js.LICENSE.txt → 981.e360e7df.js.LICENSE.txt} +0 -0
  107. /package/__mf/js/async/{lib-router.098fc614.js.LICENSE.txt → lib-router.25a1f509.js.LICENSE.txt} +0 -0
@@ -0,0 +1,246 @@
1
+ // Copyright 2023 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
+ escapeCsvValue: function() {
25
+ return escapeCsvValue;
26
+ },
27
+ exportDataAsCSV: function() {
28
+ return exportDataAsCSV;
29
+ },
30
+ extractExportableData: function() {
31
+ return extractExportableData;
32
+ },
33
+ formatLegendName: function() {
34
+ return formatLegendName;
35
+ },
36
+ formatTimestampISO: function() {
37
+ return formatTimestampISO;
38
+ },
39
+ isExportableData: function() {
40
+ return isExportableData;
41
+ },
42
+ sanitizeColumnName: function() {
43
+ return sanitizeColumnName;
44
+ },
45
+ sanitizeFilename: function() {
46
+ return sanitizeFilename;
47
+ }
48
+ });
49
+ const isExportableData = (data)=>{
50
+ return !!(data && typeof data === 'object' && 'series' in data && Array.isArray(data.series) && data.series.length > 0);
51
+ };
52
+ const extractExportableData = (queryResults)=>{
53
+ if (!queryResults || queryResults.length === 0) return undefined;
54
+ const allSeries = [];
55
+ let timeRange = undefined;
56
+ let stepMs = undefined;
57
+ let metadata = undefined;
58
+ queryResults.forEach((query)=>{
59
+ if (query?.data && typeof query.data === 'object' && 'series' in query.data) {
60
+ const data = query.data;
61
+ if (data.series && Array.isArray(data.series) && data.series.length > 0) {
62
+ allSeries.push(...data.series);
63
+ if (!timeRange && data.timeRange) {
64
+ timeRange = data.timeRange;
65
+ }
66
+ if (!stepMs && data.stepMs) {
67
+ stepMs = data.stepMs;
68
+ }
69
+ if (!metadata && data.metadata) {
70
+ metadata = data.metadata;
71
+ }
72
+ }
73
+ }
74
+ });
75
+ if (allSeries.length > 0) {
76
+ return {
77
+ series: allSeries,
78
+ timeRange,
79
+ stepMs,
80
+ metadata
81
+ };
82
+ }
83
+ return undefined;
84
+ };
85
+ const formatLegendName = (series, seriesIndex)=>{
86
+ const seriesAny = series;
87
+ let legendName = series.formattedName || series.name;
88
+ if (!legendName || legendName === `Series ${seriesIndex + 1}`) {
89
+ legendName = seriesAny.legendName || seriesAny.displayName || seriesAny.legend || series.name || '';
90
+ }
91
+ if ((!legendName || legendName === series.name) && series.labels) {
92
+ const labels = series.labels;
93
+ const displayLabels = {
94
+ ...labels
95
+ };
96
+ const metricName = displayLabels.__name__;
97
+ delete displayLabels.__name__;
98
+ const labelPairs = Object.entries(displayLabels).filter(([value])=>value !== undefined && value !== null && value !== '').map(([key, value])=>`${key}="${value}"`).join(', ');
99
+ if (metricName && labelPairs) {
100
+ legendName = `${metricName}{${labelPairs}}`;
101
+ } else if (metricName) {
102
+ legendName = metricName;
103
+ } else if (labelPairs) {
104
+ legendName = `{${labelPairs}}`;
105
+ } else {
106
+ legendName = labels.job || labels.instance || labels.metric || `Series ${seriesIndex + 1}`;
107
+ }
108
+ }
109
+ if (!legendName || legendName.trim() === '') {
110
+ legendName = `Series ${seriesIndex + 1}`;
111
+ }
112
+ return legendName;
113
+ };
114
+ const sanitizeColumnName = (name)=>{
115
+ return name.replace(/[,"\n\r]/g, '_').replace(/\s+/g, '_').replace(/_+/g, '_').replace(/^_|_$/g, '').substring(0, 255);
116
+ };
117
+ const sanitizeFilename = (filename)=>{
118
+ return filename.replace(/[<>:"/\\|?*]/g, ' ').trim().split(/\s+/).filter((word)=>word.length > 0).map((word, index)=>{
119
+ if (index === 0) {
120
+ return word.toLowerCase();
121
+ }
122
+ return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
123
+ }).join('');
124
+ };
125
+ const formatTimestampISO = (timestamp)=>{
126
+ let timestampMs;
127
+ if (typeof timestamp === 'string') {
128
+ const date = new Date(timestamp);
129
+ if (isNaN(date.getTime())) {
130
+ return timestamp;
131
+ }
132
+ timestampMs = date.getTime();
133
+ } else {
134
+ timestampMs = timestamp > 1e10 ? timestamp : timestamp * 1000;
135
+ }
136
+ const date = new Date(timestampMs);
137
+ if (isNaN(date.getTime())) {
138
+ return new Date(timestampMs).toISOString();
139
+ }
140
+ return date.toISOString();
141
+ };
142
+ const escapeCsvValue = (value)=>{
143
+ if (value === null || value === undefined) {
144
+ return '';
145
+ }
146
+ const stringValue = String(value);
147
+ if (stringValue.includes(',') || stringValue.includes('"') || stringValue.includes('\n') || stringValue.includes('\r')) {
148
+ return `"${stringValue.replace(/"/g, '""')}"`;
149
+ }
150
+ return stringValue;
151
+ };
152
+ const exportDataAsCSV = ({ data })=>{
153
+ if (!isExportableData(data)) {
154
+ console.warn('No valid data found to export to CSV.');
155
+ return new Blob([
156
+ ''
157
+ ], {
158
+ type: 'text/csv;charset=utf-8'
159
+ });
160
+ }
161
+ let csvString = '';
162
+ const result = {};
163
+ const seriesInfo = [];
164
+ let validSeriesCount = 0;
165
+ for(let i = 0; i < data.series.length; i++){
166
+ const series = data.series[i];
167
+ if (!series) {
168
+ continue;
169
+ }
170
+ if (!Array.isArray(series.values) || series.values.length === 0) {
171
+ continue;
172
+ }
173
+ const legendName = formatLegendName(series, i);
174
+ const columnName = sanitizeColumnName(legendName);
175
+ const currentSeriesInfo = {
176
+ legendName,
177
+ columnName: columnName || `Series_${i + 1}`,
178
+ originalName: series.name || ''
179
+ };
180
+ seriesInfo.push(currentSeriesInfo);
181
+ validSeriesCount++;
182
+ for(let j = 0; j < series.values.length; j++){
183
+ const entry = series.values[j];
184
+ let timestamp;
185
+ let value;
186
+ if (Array.isArray(entry) && entry.length >= 2) {
187
+ timestamp = entry[0];
188
+ value = entry[1];
189
+ } else if (typeof entry === 'object' && entry !== null && 'timestamp' in entry && 'value' in entry) {
190
+ const dataPoint = entry;
191
+ timestamp = dataPoint.timestamp;
192
+ value = dataPoint.value;
193
+ } else {
194
+ continue;
195
+ }
196
+ if (value === null || value === undefined) {
197
+ continue;
198
+ }
199
+ const dateTime = formatTimestampISO(timestamp);
200
+ if (!result[dateTime]) {
201
+ result[dateTime] = {};
202
+ }
203
+ result[dateTime][currentSeriesInfo.columnName] = value;
204
+ }
205
+ }
206
+ if (validSeriesCount === 0 || seriesInfo.length === 0) {
207
+ console.warn('No valid data found to export to CSV.');
208
+ return new Blob([
209
+ ''
210
+ ], {
211
+ type: 'text/csv;charset=utf-8'
212
+ });
213
+ }
214
+ const timestampCount = Object.keys(result).length;
215
+ if (timestampCount === 0) {
216
+ console.warn('No valid timestamp data found to export to CSV.');
217
+ return new Blob([
218
+ ''
219
+ ], {
220
+ type: 'text/csv;charset=utf-8'
221
+ });
222
+ }
223
+ const columnNames = seriesInfo.map((info)=>info.columnName);
224
+ csvString += `DateTime,${columnNames.join(',')}\n`;
225
+ const sortedDateTimes = Object.keys(result).sort((a, b)=>{
226
+ const dateA = new Date(a).getTime();
227
+ const dateB = new Date(b).getTime();
228
+ return dateA - dateB;
229
+ });
230
+ for (const dateTime of sortedDateTimes){
231
+ const rowData = result[dateTime];
232
+ const values = [];
233
+ if (rowData) {
234
+ for (const columnName of columnNames){
235
+ const value = rowData[columnName];
236
+ values.push(escapeCsvValue(value));
237
+ }
238
+ csvString += `${escapeCsvValue(dateTime)},${values.join(',')}\n`;
239
+ }
240
+ }
241
+ return new Blob([
242
+ csvString
243
+ ], {
244
+ type: 'text/csv;charset=utf-8'
245
+ });
246
+ };
@@ -23,6 +23,7 @@ Object.defineProperty(exports, "TimeSeriesChart", {
23
23
  const _timeserieschartmodel = require("./time-series-chart-model");
24
24
  const _TimeSeriesChartOptionsEditorSettings = require("./TimeSeriesChartOptionsEditorSettings");
25
25
  const _TimeSeriesChartPanel = require("./TimeSeriesChartPanel");
26
+ const _TimeSeriesExportAction = require("./TimeSeriesExportAction");
26
27
  const TimeSeriesChart = {
27
28
  PanelComponent: _TimeSeriesChartPanel.TimeSeriesChartPanel,
28
29
  supportedQueryTypes: [
@@ -34,5 +35,11 @@ const TimeSeriesChart = {
34
35
  content: _TimeSeriesChartOptionsEditorSettings.TimeSeriesChartOptionsEditorSettings
35
36
  }
36
37
  ],
37
- createInitialOptions: _timeserieschartmodel.createInitialTimeSeriesChartOptions
38
+ createInitialOptions: _timeserieschartmodel.createInitialTimeSeriesChartOptions,
39
+ actions: [
40
+ {
41
+ component: _TimeSeriesExportAction.TimeSeriesExportAction,
42
+ location: 'header'
43
+ }
44
+ ]
38
45
  };
@@ -52,7 +52,7 @@ function _interop_require_default(obj) {
52
52
  _renderers.CanvasRenderer
53
53
  ]);
54
54
  const TimeSeriesChartBase = /*#__PURE__*/ (0, _react.forwardRef)(function TimeChart({ height, data, seriesMapping, timeScale: timeScaleProp, yAxis, format, grid, isStackedBar = false, tooltipConfig = _components1.DEFAULT_TOOLTIP_CONFIG, noDataVariant = 'message', syncGroup, onDataZoom, onDoubleClick, __experimentalEChartsOptionsOverride }, ref) {
55
- const { chartsTheme, enablePinning, lastTooltipPinnedCoords, setLastTooltipPinnedCoords } = (0, _components1.useChartsContext)();
55
+ const { chartsTheme, enablePinning, enableSyncGrouping, lastTooltipPinnedCoords, setLastTooltipPinnedCoords } = (0, _components1.useChartsContext)();
56
56
  const isPinningEnabled = tooltipConfig.enablePinning && enablePinning;
57
57
  const chartRef = (0, _react.useRef)();
58
58
  const [showTooltip, setShowTooltip] = (0, _react.useState)(true);
@@ -395,7 +395,7 @@ const TimeSeriesChartBase = /*#__PURE__*/ (0, _react.forwardRef)(function TimeCh
395
395
  theme: chartsTheme.echartsTheme,
396
396
  onEvents: handleEvents,
397
397
  _instance: chartRef,
398
- syncGroup: syncGroup
398
+ syncGroup: enableSyncGrouping ? syncGroup : undefined
399
399
  })
400
400
  ]
401
401
  });
@@ -62,6 +62,7 @@ function TimeSeriesChartOptionsEditorSettings(props) {
62
62
  /*#__PURE__*/ (0, _jsxruntime.jsxs)(_components.OptionsEditorColumn, {
63
63
  children: [
64
64
  /*#__PURE__*/ (0, _jsxruntime.jsx)(_pluginsystem.LegendOptionsEditor, {
65
+ calculation: "aggregation",
65
66
  value: value.legend,
66
67
  onChange: handleLegendChange
67
68
  }),
@@ -0,0 +1,123 @@
1
+ // Copyright 2023 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, "TimeSeriesExportAction", {
18
+ enumerable: true,
19
+ get: function() {
20
+ return TimeSeriesExportAction;
21
+ }
22
+ });
23
+ const _jsxruntime = require("react/jsx-runtime");
24
+ const _react = /*#__PURE__*/ _interop_require_wildcard(require("react"));
25
+ const _material = require("@mui/material");
26
+ const _Download = /*#__PURE__*/ _interop_require_default(require("mdi-material-ui/Download"));
27
+ const _CSVExportUtils = require("./CSVExportUtils");
28
+ function _interop_require_default(obj) {
29
+ return obj && obj.__esModule ? obj : {
30
+ default: obj
31
+ };
32
+ }
33
+ function _getRequireWildcardCache(nodeInterop) {
34
+ if (typeof WeakMap !== "function") return null;
35
+ var cacheBabelInterop = new WeakMap();
36
+ var cacheNodeInterop = new WeakMap();
37
+ return (_getRequireWildcardCache = function(nodeInterop) {
38
+ return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
39
+ })(nodeInterop);
40
+ }
41
+ function _interop_require_wildcard(obj, nodeInterop) {
42
+ if (!nodeInterop && obj && obj.__esModule) {
43
+ return obj;
44
+ }
45
+ if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
46
+ return {
47
+ default: obj
48
+ };
49
+ }
50
+ var cache = _getRequireWildcardCache(nodeInterop);
51
+ if (cache && cache.has(obj)) {
52
+ return cache.get(obj);
53
+ }
54
+ var newObj = {
55
+ __proto__: null
56
+ };
57
+ var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
58
+ for(var key in obj){
59
+ if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
60
+ var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
61
+ if (desc && (desc.get || desc.set)) {
62
+ Object.defineProperty(newObj, key, desc);
63
+ } else {
64
+ newObj[key] = obj[key];
65
+ }
66
+ }
67
+ }
68
+ newObj.default = obj;
69
+ if (cache) {
70
+ cache.set(obj, newObj);
71
+ }
72
+ return newObj;
73
+ }
74
+ const TimeSeriesExportAction = ({ queryResults, definition })=>{
75
+ const exportableData = (0, _react.useMemo)(()=>{
76
+ return (0, _CSVExportUtils.extractExportableData)(queryResults);
77
+ }, [
78
+ queryResults
79
+ ]);
80
+ const canExport = (0, _react.useMemo)(()=>{
81
+ return (0, _CSVExportUtils.isExportableData)(exportableData);
82
+ }, [
83
+ exportableData
84
+ ]);
85
+ const handleExport = (0, _react.useCallback)(()=>{
86
+ if (!exportableData || !canExport) return;
87
+ try {
88
+ const title = definition?.spec?.display?.name || 'Time Series Data';
89
+ const csvBlob = (0, _CSVExportUtils.exportDataAsCSV)({
90
+ data: exportableData
91
+ });
92
+ const baseFilename = (0, _CSVExportUtils.sanitizeFilename)(title);
93
+ const filename = `${baseFilename}_data.csv`;
94
+ const link = document.createElement('a');
95
+ link.href = URL.createObjectURL(csvBlob);
96
+ link.download = filename;
97
+ document.body.appendChild(link);
98
+ link.click();
99
+ document.body.removeChild(link);
100
+ URL.revokeObjectURL(link.href);
101
+ } catch (error) {
102
+ console.error('Time series export failed:', error);
103
+ }
104
+ }, [
105
+ exportableData,
106
+ canExport,
107
+ definition
108
+ ]);
109
+ if (!canExport) {
110
+ return null;
111
+ }
112
+ return /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Tooltip, {
113
+ title: "Export as CSV",
114
+ children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.IconButton, {
115
+ size: "small",
116
+ onClick: handleExport,
117
+ "aria-label": "Export time series data as CSV",
118
+ children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_Download.default, {
119
+ fontSize: "inherit"
120
+ })
121
+ })
122
+ });
123
+ };
package/lib/cjs/index.js CHANGED
@@ -29,6 +29,7 @@ _export_star(require("./YAxisOptionsEditor"), exports);
29
29
  _export_star(require("./TimeSeriesChartPanel"), exports);
30
30
  _export_star(require("./TimeSeriesChartBase"), exports);
31
31
  _export_star(require("./time-series-chart-model"), exports);
32
+ _export_star(require("./CSVExportUtils"), exports);
32
33
  function _export_star(from, to) {
33
34
  Object.keys(from).forEach(function(k) {
34
35
  if (k !== "default" && !Object.prototype.hasOwnProperty.call(to, k)) {
package/lib/index.d.ts CHANGED
@@ -7,4 +7,5 @@ export * from './YAxisOptionsEditor';
7
7
  export * from './TimeSeriesChartPanel';
8
8
  export * from './TimeSeriesChartBase';
9
9
  export * from './time-series-chart-model';
10
+ export * from './CSVExportUtils';
10
11
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,cAAc,mBAAmB,CAAC;AAClC,cAAc,uBAAuB,CAAC;AACtC,cAAc,wCAAwC,CAAC;AACvD,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,2BAA2B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,cAAc,mBAAmB,CAAC;AAClC,cAAc,uBAAuB,CAAC;AACtC,cAAc,wCAAwC,CAAC;AACvD,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,kBAAkB,CAAC"}
package/lib/index.js CHANGED
@@ -19,5 +19,6 @@ export * from './YAxisOptionsEditor';
19
19
  export * from './TimeSeriesChartPanel';
20
20
  export * from './TimeSeriesChartBase';
21
21
  export * from './time-series-chart-model';
22
+ export * from './CSVExportUtils';
22
23
 
23
24
  //# sourceMappingURL=index.js.map
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/index.ts"],"sourcesContent":["// Copyright 2025 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\nexport { getPluginModule } from './getPluginModule';\nexport * from './TimeSeriesChart';\nexport * from './QuerySettingsEditor';\nexport * from './TimeSeriesChartOptionsEditorSettings';\nexport * from './VisualOptionsEditor';\nexport * from './YAxisOptionsEditor';\nexport * from './TimeSeriesChartPanel';\nexport * from './TimeSeriesChartBase';\nexport * from './time-series-chart-model';\n"],"names":["getPluginModule"],"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;AAEjC,SAASA,eAAe,QAAQ,oBAAoB;AACpD,cAAc,oBAAoB;AAClC,cAAc,wBAAwB;AACtC,cAAc,yCAAyC;AACvD,cAAc,wBAAwB;AACtC,cAAc,uBAAuB;AACrC,cAAc,yBAAyB;AACvC,cAAc,wBAAwB;AACtC,cAAc,4BAA4B"}
1
+ {"version":3,"sources":["../../src/index.ts"],"sourcesContent":["// Copyright 2025 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\nexport { getPluginModule } from './getPluginModule';\nexport * from './TimeSeriesChart';\nexport * from './QuerySettingsEditor';\nexport * from './TimeSeriesChartOptionsEditorSettings';\nexport * from './VisualOptionsEditor';\nexport * from './YAxisOptionsEditor';\nexport * from './TimeSeriesChartPanel';\nexport * from './TimeSeriesChartBase';\nexport * from './time-series-chart-model';\nexport * from './CSVExportUtils';\n"],"names":["getPluginModule"],"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;AAEjC,SAASA,eAAe,QAAQ,oBAAoB;AACpD,cAAc,oBAAoB;AAClC,cAAc,wBAAwB;AACtC,cAAc,yCAAyC;AACvD,cAAc,wBAAwB;AACtC,cAAc,uBAAuB;AACrC,cAAc,yBAAyB;AACvC,cAAc,wBAAwB;AACtC,cAAc,4BAA4B;AAC1C,cAAc,mBAAmB"}