@perses-dev/timeseries-chart-plugin 0.14.0-beta.6 → 0.14.0-beta.8

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 (77) hide show
  1. package/README.md +11 -0
  2. package/__mf/js/TimeSeriesChart.aa6aa96b.js +7 -0
  3. package/__mf/js/async/{1616.7cf381f0.js → 1616.2ad408f8.js} +1 -1
  4. package/__mf/js/async/2490.7e5650e7.js +2 -0
  5. package/__mf/js/async/{3068.50ed57d5.js → 3068.c95fecc7.js} +9 -9
  6. package/__mf/js/async/{5259.f3284aaa.js → 3441.65e1728a.js} +6 -6
  7. package/__mf/js/async/{392.6343c7ea.js → 392.11188127.js} +2 -2
  8. package/__mf/js/async/{4077.62433b15.js → 4077.cf1d675f.js} +1 -1
  9. package/__mf/js/async/{4121.82a6a52c.js → 4121.2a21582b.js} +2 -2
  10. package/__mf/js/async/{4134.a94fc299.js → 4134.9d3e6a8b.js} +1 -1
  11. package/__mf/js/async/{4496.b0d93933.js → 4496.eb53e477.js} +1 -1
  12. package/__mf/js/async/{4670.8e9fc9b1.js → 4670.b5dafbaa.js} +1 -1
  13. package/__mf/js/async/{5002.0d0c2f26.js → 5002.e3ab6daa.js} +1 -1
  14. package/__mf/js/async/{5071.ef93b262.js → 5071.586de8fa.js} +1 -1
  15. package/__mf/js/async/{5182.ac39e54d.js → 5182.375bbf8e.js} +2 -2
  16. package/__mf/js/async/5394.f1c40599.js +7 -0
  17. package/__mf/js/async/{5587.1f4e28c2.js → 5587.bfa64ec3.js} +1 -1
  18. package/__mf/js/async/{6274.e416bf61.js → 6274.c6a9892d.js} +2 -2
  19. package/__mf/js/async/6625.e3624f20.js +1 -0
  20. package/__mf/js/async/{7151.e70d1dc9.js → 7151.f8879976.js} +1 -1
  21. package/__mf/js/async/{7192.88142d8c.js → 7192.f5f93b5e.js} +1 -1
  22. package/__mf/js/async/{7319.4208aea7.js → 7319.3e3c9686.js} +1 -1
  23. package/__mf/js/async/{7384.fa3f2d0e.js → 7384.4be917ee.js} +1 -1
  24. package/__mf/js/async/{7633.6805cb60.js → 7633.9cb6de7a.js} +2 -2
  25. package/__mf/js/async/{7955.ab1cde16.js → 7955.877daa4d.js} +1 -1
  26. package/__mf/js/async/{7968.f59b65d1.js → 7968.cf8a4d6a.js} +1 -1
  27. package/__mf/js/async/{7978.c2017f6b.js → 7978.67c99e22.js} +1 -1
  28. package/__mf/js/async/{8356.f0faaf86.js → 8356.b7f7e7f3.js} +1 -1
  29. package/__mf/js/async/{8465.a4e88d99.js → 8465.56096f79.js} +1 -1
  30. package/__mf/js/async/{8470.c382605c.js → 8470.f137ffe2.js} +2 -2
  31. package/__mf/js/async/{8724.e0b36d16.js → 8724.0d169bb2.js} +1 -1
  32. package/__mf/js/async/{873.4fec300c.js → 873.b41b449a.js} +1 -1
  33. package/__mf/js/async/{9235.e1b40e38.js → 9235.4831e488.js} +1 -1
  34. package/__mf/js/async/{941.bdba80db.js → 941.76f11ced.js} +2 -2
  35. package/__mf/js/async/{9588.62f5ed3b.js → 9588.883e3395.js} +1 -1
  36. package/__mf/js/async/{9700.3cea5abe.js → 9700.628e2532.js} +1 -1
  37. package/__mf/js/async/__federation_expose_TimeSeriesChart.40d2d053.js +1 -0
  38. package/__mf/js/async/lib-router.4f5ed027.js +2 -0
  39. package/__mf/js/async/{lib-router.aeb226c2.js.LICENSE.txt → lib-router.4f5ed027.js.LICENSE.txt} +3 -3
  40. package/__mf/js/main.7434d87e.js +7 -0
  41. package/lib/TimeSeriesChartBase.d.ts +3 -0
  42. package/lib/TimeSeriesChartBase.d.ts.map +1 -1
  43. package/lib/TimeSeriesChartBase.js +183 -58
  44. package/lib/TimeSeriesChartBase.js.map +1 -1
  45. package/lib/TimeSeriesChartPanel.d.ts +3 -1
  46. package/lib/TimeSeriesChartPanel.d.ts.map +1 -1
  47. package/lib/TimeSeriesChartPanel.js +190 -113
  48. package/lib/TimeSeriesChartPanel.js.map +1 -1
  49. package/lib/test/mock-query-results.d.ts +2 -1
  50. package/lib/test/mock-query-results.d.ts.map +1 -1
  51. package/lib/test/mock-query-results.js +40 -0
  52. package/lib/test/mock-query-results.js.map +1 -1
  53. package/lib/utils/data-transform.d.ts +30 -3
  54. package/lib/utils/data-transform.d.ts.map +1 -1
  55. package/lib/utils/data-transform.js +41 -7
  56. package/lib/utils/data-transform.js.map +1 -1
  57. package/mf-manifest.json +45 -45
  58. package/mf-stats.json +45 -45
  59. package/package.json +5 -5
  60. package/__mf/js/TimeSeriesChart.d4c34278.js +0 -7
  61. package/__mf/js/async/702.f05e4a6a.js +0 -2
  62. package/__mf/js/async/7491.68fb6045.js +0 -1
  63. package/__mf/js/async/8391.3445b0cf.js +0 -7
  64. package/__mf/js/async/__federation_expose_TimeSeriesChart.75ec8151.js +0 -1
  65. package/__mf/js/async/lib-router.aeb226c2.js +0 -2
  66. package/__mf/js/main.d94da6a3.js +0 -7
  67. /package/__mf/css/async/{8391.85c2cbf6.css → 5394.85c2cbf6.css} +0 -0
  68. /package/__mf/js/async/{702.f05e4a6a.js.LICENSE.txt → 2490.7e5650e7.js.LICENSE.txt} +0 -0
  69. /package/__mf/js/async/{3068.50ed57d5.js.LICENSE.txt → 3068.c95fecc7.js.LICENSE.txt} +0 -0
  70. /package/__mf/js/async/{392.6343c7ea.js.LICENSE.txt → 392.11188127.js.LICENSE.txt} +0 -0
  71. /package/__mf/js/async/{4121.82a6a52c.js.LICENSE.txt → 4121.2a21582b.js.LICENSE.txt} +0 -0
  72. /package/__mf/js/async/{5182.ac39e54d.js.LICENSE.txt → 5182.375bbf8e.js.LICENSE.txt} +0 -0
  73. /package/__mf/js/async/{8391.3445b0cf.js.LICENSE.txt → 5394.f1c40599.js.LICENSE.txt} +0 -0
  74. /package/__mf/js/async/{6274.e416bf61.js.LICENSE.txt → 6274.c6a9892d.js.LICENSE.txt} +0 -0
  75. /package/__mf/js/async/{7633.6805cb60.js.LICENSE.txt → 7633.9cb6de7a.js.LICENSE.txt} +0 -0
  76. /package/__mf/js/async/{8470.c382605c.js.LICENSE.txt → 8470.f137ffe2.js.LICENSE.txt} +0 -0
  77. /package/__mf/js/async/{941.bdba80db.js.LICENSE.txt → 941.76f11ced.js.LICENSE.txt} +0 -0
@@ -16,12 +16,21 @@ import { YAxisLabel, useChartsTheme, ContentWithLegend, useId, DEFAULT_TOOLTIP_C
16
16
  import { usePanelAnnotationsWithData } from "@perses-dev/dashboards";
17
17
  import { LEGEND_VALUE_CONFIG, useTimeRange, validateLegendSpec, legendValues, getCalculations } from "@perses-dev/plugin-system";
18
18
  import merge from "lodash/merge";
19
- import { useMemo, useRef, useState } from "react";
19
+ import { memo, useCallback, useMemo, useRef, useState } from "react";
20
20
  import { DEFAULT_FORMAT, DEFAULT_VISUAL, THRESHOLD_PLOT_INTERVAL } from "./time-series-chart-model.js";
21
21
  import { TimeSeriesChartBase } from "./TimeSeriesChartBase.js";
22
22
  import { convertAnnotationToTimeSeriesAnnotation } from "./utils/annotation.js";
23
23
  import { getTimeSeries, getCommonTimeScaleForQueries, convertPanelYAxis, getThresholdSeries, convertPercentThreshold } from "./utils/data-transform.js";
24
24
  import { getSeriesColor } from "./utils/palette-gen.js";
25
+ /**
26
+ * Stable string key for a labels record, so exemplars can be matched to their
27
+ * series regardless of the labels order.
28
+ */ function labelsKey(labels) {
29
+ return JSON.stringify(Object.keys(labels).toSorted().map((labelName)=>[
30
+ labelName,
31
+ labels[labelName]
32
+ ]));
33
+ }
25
34
  // Using an "ALL" value to handle the case on first loading the chart where we
26
35
  // want to select all, but do not want all of the legend items to be visually highlighted.
27
36
  // This helps us differentiate those cases more clearly instead of inferring it
@@ -30,7 +39,7 @@ import { getSeriesColor } from "./utils/palette-gen.js";
30
39
  // currently require significantly more refactoring of this component.
31
40
  // TODO: simplify this if we switch the list-based legend UI to use checkboxes,
32
41
  // where we *would* want to visually select all items in this case.
33
- export function TimeSeriesChartPanel(props) {
42
+ function TimeSeriesChartPanelComponent(props) {
34
43
  const { spec: { thresholds, yAxis, tooltip, querySettings: querySettingsList }, contentDimensions, queryResults } = props;
35
44
  const chartsTheme = useChartsTheme();
36
45
  const muiTheme = useTheme();
@@ -72,11 +81,10 @@ export function TimeSeriesChartPanel(props) {
72
81
  ]);
73
82
  // Collect unique formats from query settings that differ from the base format
74
83
  // These will create additional Y axes on the right side
75
- const { additionalFormats, formatToYAxisIndex, seriesFormatMap } = useMemo(()=>{
84
+ const { additionalFormats, formatToYAxisIndex } = useMemo(()=>{
76
85
  const baseUnit = format?.unit ?? 'decimal';
77
86
  const additionalFormats = [];
78
87
  const formatToYAxisIndex = new Map();
79
- const seriesFormatMap = new Map();
80
88
  // Index 0 is reserved for the base Y axis
81
89
  formatToYAxisIndex.set(baseUnit, 0);
82
90
  // Collect unique formats from query settings
@@ -92,8 +100,7 @@ export function TimeSeriesChartPanel(props) {
92
100
  }
93
101
  return {
94
102
  additionalFormats,
95
- formatToYAxisIndex,
96
- seriesFormatMap
103
+ formatToYAxisIndex
97
104
  };
98
105
  }, [
99
106
  format,
@@ -106,13 +113,112 @@ export function TimeSeriesChartPanel(props) {
106
113
  const annotations = useMemo(()=>convertAnnotationToTimeSeriesAnnotation(annotationsWithData), [
107
114
  annotationsWithData
108
115
  ]);
116
+ const calculationTypes = legend?.values;
117
+ // Point processing and legend statistics depend on query data, not legend selection.
118
+ // Reuse these arrays when toggling series instead of rescanning every sample.
119
+ const { timeScale, preparedQueries } = useMemo(()=>{
120
+ const commonScale = getCommonTimeScaleForQueries(queryResults);
121
+ const settingsByQuery = new Map(querySettingsList?.map((settings)=>[
122
+ settings.queryIndex,
123
+ settings
124
+ ]));
125
+ let seriesIndex = 0;
126
+ const queries = commonScale ? queryResults.map((result, queryIndex)=>{
127
+ const querySettings = settingsByQuery.get(queryIndex);
128
+ const series = result.data.series.map((timeSeries)=>{
129
+ const baseValues = getTimeSeriesValues(timeSeries, commonScale);
130
+ const values = querySettings?.negativeY ? baseValues.map(([t, v])=>[
131
+ t,
132
+ v === null ? null : -v
133
+ ]) : baseValues;
134
+ const calculations = calculationTypes ? getCalculations(timeSeries.values, calculationTypes) : undefined;
135
+ let maxValue = 0;
136
+ if (querySettings?.format?.unit) {
137
+ for (const [, value] of timeSeries.values){
138
+ maxValue = Math.max(maxValue, Math.abs(value ?? 0));
139
+ }
140
+ }
141
+ const seriesId = `${chartId}${timeSeries.name}${seriesIndex}`;
142
+ seriesIndex += 1;
143
+ return {
144
+ timeSeries,
145
+ seriesId,
146
+ values,
147
+ calculations,
148
+ maxValue
149
+ };
150
+ });
151
+ return {
152
+ querySettings,
153
+ series,
154
+ exemplars: result.data.exemplars
155
+ };
156
+ }) : [];
157
+ return {
158
+ timeScale: commonScale,
159
+ preparedQueries: queries
160
+ };
161
+ }, [
162
+ queryResults,
163
+ querySettingsList,
164
+ calculationTypes,
165
+ chartId
166
+ ]);
167
+ // Prepare all exemplar groups independently of legend selection. The base chart
168
+ // filters their scatter series without rebuilding marker data for visible groups.
169
+ const chartExemplars = useMemo(()=>{
170
+ const groups = [];
171
+ let seriesIndex = 0;
172
+ for (const { querySettings, series, exemplars } of preparedQueries){
173
+ // Labels identify a series within a query, not across different queries.
174
+ const seriesByLabels = new Map();
175
+ for (const { timeSeries, seriesId } of series){
176
+ const seriesName = timeSeries.formattedName ?? timeSeries.name;
177
+ if (exemplars?.length && timeSeries.labels) {
178
+ seriesByLabels.set(labelsKey(timeSeries.labels), {
179
+ seriesId,
180
+ seriesName,
181
+ color: getSeriesColor({
182
+ categoricalPalette: categoricalPalette,
183
+ visual,
184
+ muiPrimaryColor: muiTheme.palette.primary.main,
185
+ seriesName,
186
+ seriesIndex,
187
+ querySettings,
188
+ queryHasMultipleResults: series.length > 1
189
+ }),
190
+ seriesLabels: timeSeries.labels,
191
+ yAxisIndex: formatToYAxisIndex.get(querySettings?.format?.unit ?? '') ?? 0,
192
+ negativeY: querySettings?.negativeY,
193
+ exemplars: []
194
+ });
195
+ }
196
+ seriesIndex++;
197
+ }
198
+ for (const group of exemplars ?? []){
199
+ if (group.exemplars.length === 0) continue;
200
+ const matched = seriesByLabels.get(labelsKey(group.seriesLabels));
201
+ if (matched) groups.push({
202
+ ...matched,
203
+ exemplars: group.exemplars
204
+ });
205
+ }
206
+ }
207
+ return groups;
208
+ }, [
209
+ preparedQueries,
210
+ categoricalPalette,
211
+ visual,
212
+ muiTheme.palette.primary.main,
213
+ formatToYAxisIndex
214
+ ]);
109
215
  // Populate series data based on query results
110
- const { timeScale, timeChartData, timeSeriesMapping, legendItems, seriesFormatMap: computedSeriesFormatMap, maxValuesByFormat } = useMemo(()=>{
111
- const timeScale = getCommonTimeScaleForQueries(queryResults);
216
+ const { timeChartData, timeSeriesMapping, legendItems, seriesFormatMap: computedSeriesFormatMap, maxValuesByFormat } = useMemo(()=>{
112
217
  if (timeScale === undefined) {
113
218
  return {
114
219
  timeChartData: [],
115
220
  timeSeriesMapping: [],
221
+ legendItems: [],
116
222
  seriesFormatMap: new Map(),
117
223
  maxValuesByFormat: new Map()
118
224
  };
@@ -124,106 +230,73 @@ export function TimeSeriesChartPanel(props) {
124
230
  const timeSeriesMapping = [];
125
231
  // Track max values for each format unit (used for dynamic Y axis offset calculation)
126
232
  const maxValuesByFormat = new Map();
233
+ const seriesFormatMap = new Map();
234
+ let visibleSeriesCount = 0;
235
+ for (const { series } of preparedQueries){
236
+ for (const { seriesId } of series){
237
+ if (selectedLegendItems === 'ALL' || selectedLegendItems[seriesId]) visibleSeriesCount++;
238
+ }
239
+ }
127
240
  // Index is counted across multiple queries which ensures the categorical color palette does not reset for every query
128
241
  let seriesIndex = 0;
129
- // Mapping of each set of query results to be ECharts option compatible
130
- // TODO: Look into performance optimizations and moving parts of mapping to the lower level chart
131
- for(let queryIndex = 0; queryIndex < queryResults.length; queryIndex++){
132
- const result = queryResults[queryIndex];
133
- // Retrieve querySettings for this query, if exists.
134
- // queries & querySettings indices do not necessarily match, so we have to check the tail value of the $ref attribute
135
- let querySettings;
136
- for (const item of querySettingsList ?? []){
137
- if (item.queryIndex === queryIndex) {
138
- querySettings = item;
139
- // We don't break the loop here just in case there are multiple querySettings defined for the
140
- // same queryIndex, because in that case we want the last one to take precedence.
141
- }
142
- }
143
- if (result) {
144
- for(let i = 0; i < result.data.series.length; i++){
145
- const timeSeries = result.data.series[i];
146
- if (timeSeries === undefined) {
147
- return {
148
- timeChartData: [],
149
- timeSeriesMapping: [],
150
- legendItems: []
151
- };
152
- }
153
- // Format is determined by seriesNameFormat in query spec
154
- const formattedSeriesName = timeSeries.formattedName ?? timeSeries.name;
155
- // Color is used for line, tooltip, and legend
156
- const seriesColor = getSeriesColor({
157
- // ECharts type for color is not always an array but it is always an array in ChartsProvider
158
- categoricalPalette: categoricalPalette,
159
- visual,
160
- muiPrimaryColor: muiTheme.palette.primary.main,
161
- seriesName: formattedSeriesName,
162
- seriesIndex,
163
- querySettings: querySettings,
164
- queryHasMultipleResults: (queryResults[queryIndex]?.data?.series?.length ?? 0) > 1
165
- });
166
- // We add a unique id for the chart to disambiguate items across charts
167
- // when there are multiple on the page.
168
- const seriesId = chartId + timeSeries.name + seriesIndex;
169
- const legendCalculations = legend?.values ? getCalculations(timeSeries.values, legend.values) : undefined;
170
- // When we initially load the chart, we want to show all series, but
171
- // DO NOT want to visualy highlight all the items in the legend.
172
- const isSelectAll = selectedLegendItems === 'ALL';
173
- const isSelected = !isSelectAll && !!selectedLegendItems[seriesId];
174
- const showTimeSeries = isSelected || isSelectAll;
175
- if (showTimeSeries) {
176
- // Use timeChartData.length to ensure the data that is passed into the tooltip accounts for
177
- // which legend items are selected. This must happen before timeChartData.push to avoid an
178
- // off-by-one error, seriesIndex cannot be used since it's needed to cycle through palette
179
- const datasetIndex = timeChartData.length;
180
- // Determine yAxisIndex based on the query's format setting
181
- const queryFormat = querySettings?.format;
182
- const yAxisIndex = queryFormat?.unit ? formatToYAxisIndex.get(queryFormat.unit) ?? 0 : 0;
183
- // Each series is stored as a separate dataset source.
184
- // https://apache.github.io/echarts-handbook/en/concepts/dataset/#how-to-reference-several-datasets
185
- timeSeriesMapping.push(getTimeSeries(seriesId, datasetIndex, formattedSeriesName, visual, timeScale, seriesColor, querySettings, yAxisIndex));
186
- // Store the format for this series for tooltip formatting
187
- if (queryFormat) {
188
- seriesFormatMap.set(seriesId, queryFormat);
189
- // Track max value for this format unit (used for dynamic Y axis offset calculation)
190
- const unitKey = queryFormat.unit;
191
- if (unitKey) {
192
- const seriesMax = Math.max(...timeSeries.values.map((v)=>Math.abs(v[1] ?? 0)));
193
- const currentMax = maxValuesByFormat.get(unitKey) ?? 0;
194
- if (seriesMax > currentMax) {
195
- maxValuesByFormat.set(unitKey, seriesMax);
196
- }
242
+ for (const { querySettings, series } of preparedQueries){
243
+ for (const { timeSeries, seriesId, values, calculations, maxValue } of series){
244
+ // Format is determined by seriesNameFormat in query spec
245
+ const formattedSeriesName = timeSeries.formattedName ?? timeSeries.name;
246
+ // Color is used for line, tooltip, and legend
247
+ const seriesColor = getSeriesColor({
248
+ // ECharts type for color is not always an array but it is always an array in ChartsProvider
249
+ categoricalPalette: categoricalPalette,
250
+ visual,
251
+ muiPrimaryColor: muiTheme.palette.primary.main,
252
+ seriesName: formattedSeriesName,
253
+ seriesIndex,
254
+ querySettings: querySettings,
255
+ queryHasMultipleResults: series.length > 1
256
+ });
257
+ // When we initially load the chart, we want to show all series, but
258
+ // DO NOT want to visualy highlight all the items in the legend.
259
+ const isSelectAll = selectedLegendItems === 'ALL';
260
+ const isSelected = !isSelectAll && !!selectedLegendItems[seriesId];
261
+ const showTimeSeries = isSelected || isSelectAll;
262
+ if (showTimeSeries) {
263
+ // Use timeChartData.length to ensure the data that is passed into the tooltip accounts for
264
+ // which legend items are selected. This must happen before timeChartData.push to avoid an
265
+ // off-by-one error, seriesIndex cannot be used since it's needed to cycle through palette
266
+ const datasetIndex = timeChartData.length;
267
+ // Determine yAxisIndex based on the query's format setting
268
+ const queryFormat = querySettings?.format;
269
+ const yAxisIndex = queryFormat?.unit ? formatToYAxisIndex.get(queryFormat.unit) ?? 0 : 0;
270
+ // Each series is stored as a separate dataset source.
271
+ // https://apache.github.io/echarts-handbook/en/concepts/dataset/#how-to-reference-several-datasets
272
+ timeSeriesMapping.push(getTimeSeries(seriesId, datasetIndex, formattedSeriesName, visual, timeScale, seriesColor, querySettings, yAxisIndex, visibleSeriesCount));
273
+ // Store the format for this series for tooltip formatting
274
+ if (queryFormat) {
275
+ seriesFormatMap.set(seriesId, queryFormat);
276
+ // Track max value for this format unit (used for dynamic Y axis offset calculation)
277
+ const unitKey = queryFormat.unit;
278
+ if (unitKey) {
279
+ const currentMax = maxValuesByFormat.get(unitKey) ?? 0;
280
+ if (maxValue > currentMax) {
281
+ maxValuesByFormat.set(unitKey, maxValue);
197
282
  }
198
283
  }
199
- // When negativeY is set on this query, negate the rendered values so the
200
- // series renders below the X axis. The original (positive) values are
201
- // preserved in `timeSeries.values` (used for legend calculations) and in
202
- // `queryResults` (used for CSV export).
203
- const baseValues = getTimeSeriesValues(timeSeries, timeScale);
204
- const renderedValues = querySettings?.negativeY ? baseValues.map((tuple)=>{
205
- const [t, v] = tuple;
206
- return [
207
- t,
208
- v === null ? null : -v
209
- ];
210
- }) : baseValues;
211
- timeChartData.push({
212
- name: formattedSeriesName,
213
- values: renderedValues
214
- });
215
- }
216
- if (legend && legendItems) {
217
- legendItems.push({
218
- id: seriesId,
219
- label: formattedSeriesName,
220
- color: seriesColor,
221
- data: legendCalculations
222
- });
223
284
  }
224
- // Used for repeating colors in Categorical palette
225
- seriesIndex++;
285
+ timeChartData.push({
286
+ name: formattedSeriesName,
287
+ values
288
+ });
226
289
  }
290
+ if (legend && legendItems) {
291
+ legendItems.push({
292
+ id: seriesId,
293
+ label: formattedSeriesName,
294
+ color: seriesColor,
295
+ data: calculations
296
+ });
297
+ }
298
+ // Used for repeating colors in Categorical palette
299
+ seriesIndex += 1;
227
300
  }
228
301
  }
229
302
  // map thresholds only if there is at least one time series to avoid displaying thresholds without any data
@@ -270,20 +343,18 @@ export function TimeSeriesChartPanel(props) {
270
343
  maxValuesByFormat
271
344
  };
272
345
  }, [
273
- queryResults,
346
+ preparedQueries,
347
+ timeScale,
274
348
  thresholds,
275
349
  selectedLegendItems,
276
350
  legend,
277
351
  visual,
278
- querySettingsList,
279
352
  yAxis?.max,
280
353
  yAxis?.min,
281
354
  categoricalPalette,
282
- chartId,
283
355
  chartsTheme.thresholds,
284
356
  muiTheme.palette.primary.main,
285
- formatToYAxisIndex,
286
- seriesFormatMap
357
+ formatToYAxisIndex
287
358
  ]);
288
359
  // Create multiple Y axes if there are additional formats
289
360
  // Uses max values from data to compute dynamic offsets that adapt to label widths
@@ -356,16 +427,17 @@ export function TimeSeriesChartPanel(props) {
356
427
  yAxis,
357
428
  additionalFormats.length
358
429
  ]);
359
- if (adjustedContentDimensions === undefined) {
360
- return null;
361
- }
362
- const handleDataZoom = (event)=>{
363
- // TODO: add ECharts transition animation on zoom
430
+ const handleDataZoom = useCallback((event)=>{
364
431
  setTimeRange({
365
432
  start: new Date(event.start),
366
433
  end: new Date(event.end)
367
434
  });
368
- };
435
+ }, [
436
+ setTimeRange
437
+ ]);
438
+ if (adjustedContentDimensions === undefined) {
439
+ return null;
440
+ }
369
441
  // Used to opt in to ECharts trigger item which show subgroup data accurately.
370
442
  // Derived from the actual series mapping rather than `visual.stack` alone so that
371
443
  // bar charts stacked only via per-query overrides also use the right tooltip mode.
@@ -427,6 +499,7 @@ export function TimeSeriesChartPanel(props) {
427
499
  height: height,
428
500
  data: timeChartData,
429
501
  seriesMapping: timeSeriesMapping,
502
+ exemplars: chartExemplars,
430
503
  annotations: annotations,
431
504
  timeScale: timeScale,
432
505
  yAxis: multipleYAxes ?? echartsYAxis,
@@ -447,5 +520,9 @@ export function TimeSeriesChartPanel(props) {
447
520
  })
448
521
  });
449
522
  }
523
+ // PanelContent recreates the queryResults array and its wrappers on dashboard
524
+ // hover/focus updates. Compare the underlying references in query order so those
525
+ // updates do not invalidate data preparation or scan the samples and exemplars.
526
+ export const TimeSeriesChartPanel = /*#__PURE__*/ memo(TimeSeriesChartPanelComponent, (previous, next)=>previous.spec === next.spec && previous.definition === next.definition && previous.contentDimensions?.width === next.contentDimensions?.width && previous.contentDimensions?.height === next.contentDimensions?.height && previous.queryResults.length === next.queryResults.length && previous.queryResults.every((query, index)=>query.data === next.queryResults[index]?.data && query.definition === next.queryResults[index]?.definition));
450
527
 
451
528
  //# sourceMappingURL=TimeSeriesChartPanel.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/TimeSeriesChartPanel.tsx"],"sourcesContent":["// Copyright 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 { Box, useTheme } from '@mui/material';\nimport type {\n ChartInstance,\n ZoomEventData,\n SelectedLegendItemState,\n TableColumnConfig,\n LegendItem,\n LegendProps,\n TooltipConfig,\n TimeChartSeriesMapping,\n StepOptions,\n} from '@perses-dev/components';\nimport {\n YAxisLabel,\n useChartsTheme,\n ContentWithLegend,\n useId,\n DEFAULT_TOOLTIP_CONFIG,\n getFormattedMultipleYAxes,\n DEFAULT_LEGEND,\n formatValue,\n getTimeSeriesValues,\n} from '@perses-dev/components';\nimport { usePanelAnnotationsWithData } from '@perses-dev/dashboards';\nimport type { PanelProps, CalculationType } from '@perses-dev/plugin-system';\nimport {\n LEGEND_VALUE_CONFIG,\n useTimeRange,\n validateLegendSpec,\n legendValues,\n getCalculations,\n} from '@perses-dev/plugin-system';\nimport type { TimeSeries, TimeSeriesData, TimeSeriesValueTuple } from '@perses-dev/spec';\nimport type { GridComponentOption } from 'echarts';\nimport merge from 'lodash/merge';\nimport type { ReactElement } from 'react';\nimport { useMemo, useRef, useState } from 'react';\n\nimport type { TimeSeriesChartOptions, QuerySettingsOptions } from './time-series-chart-model';\nimport { DEFAULT_FORMAT, DEFAULT_VISUAL, THRESHOLD_PLOT_INTERVAL } from './time-series-chart-model';\nimport { TimeSeriesChartBase } from './TimeSeriesChartBase';\nimport type { TimeSeriesAnnotation } from './utils/annotation';\nimport { convertAnnotationToTimeSeriesAnnotation } from './utils/annotation';\nimport {\n getTimeSeries,\n getCommonTimeScaleForQueries,\n convertPanelYAxis,\n getThresholdSeries,\n convertPercentThreshold,\n} from './utils/data-transform';\nimport { getSeriesColor } from './utils/palette-gen';\n\nexport type TimeSeriesChartProps = PanelProps<TimeSeriesChartOptions, TimeSeriesData>;\n\n// Using an \"ALL\" value to handle the case on first loading the chart where we\n// want to select all, but do not want all of the legend items to be visually highlighted.\n// This helps us differentiate those cases more clearly instead of inferring it\n// based on the state of the data. This also helps us avoid some coding\n// complexity around initializing a full record for the initial load that would\n// currently require significantly more refactoring of this component.\n// TODO: simplify this if we switch the list-based legend UI to use checkboxes,\n// where we *would* want to visually select all items in this case.\n\nexport function TimeSeriesChartPanel(props: TimeSeriesChartProps): ReactElement | null {\n const {\n spec: { thresholds, yAxis, tooltip, querySettings: querySettingsList },\n contentDimensions,\n queryResults,\n } = props;\n const chartsTheme = useChartsTheme();\n const muiTheme = useTheme();\n const chartId = useId('time-series-panel');\n\n const chartRef = useRef<ChartInstance>(null);\n\n // ECharts theme comes from ChartsProvider, more info: https://echarts.apache.org/en/option.html#color\n // Colors are manually applied since our legend and tooltip are built custom with React.\n const categoricalPalette = chartsTheme.echartsTheme.color;\n\n // TODO: consider refactoring how the layout/spacing/alignment are calculated\n // the next time significant changes are made to the time series panel (e.g.\n // when making improvements to the legend to more closely match designs).\n // This may also want to include moving some of this logic down to the shared,\n // embeddable components.\n const contentPadding = chartsTheme.container.padding.default;\n const adjustedContentDimensions: typeof contentDimensions = contentDimensions\n ? {\n width: contentDimensions.width - contentPadding * 2,\n height: contentDimensions.height - contentPadding * 2,\n }\n : undefined;\n\n // populate default 'position' and other future properties\n const legend = useMemo(() => {\n return props.spec.legend && validateLegendSpec(props.spec.legend)\n ? merge({}, DEFAULT_LEGEND, props.spec.legend)\n : undefined;\n }, [props.spec.legend]);\n\n // TODO: add support for y_axis_alt.format\n const format = props.spec.yAxis?.format ?? DEFAULT_FORMAT;\n\n // ensures there are fallbacks for unset properties since most\n // users should not need to customize visual display\n const visual = useMemo(() => {\n return merge({}, DEFAULT_VISUAL, props.spec.visual);\n }, [props.spec.visual]);\n\n // convert Perses dashboard format to be ECharts compatible\n const echartsYAxis = useMemo(() => {\n return convertPanelYAxis(yAxis);\n }, [yAxis]);\n\n // Collect unique formats from query settings that differ from the base format\n // These will create additional Y axes on the right side\n const { additionalFormats, formatToYAxisIndex, seriesFormatMap } = useMemo(() => {\n const baseUnit = format?.unit ?? 'decimal';\n const additionalFormats: Array<typeof format> = [];\n const formatToYAxisIndex = new Map<string, number>();\n const seriesFormatMap = new Map<string, typeof format>();\n\n // Index 0 is reserved for the base Y axis\n formatToYAxisIndex.set(baseUnit, 0);\n\n // Collect unique formats from query settings\n for (const qs of querySettingsList ?? []) {\n if (qs.format?.unit && qs.format.unit !== baseUnit) {\n const unitKey = qs.format.unit;\n if (!formatToYAxisIndex.has(unitKey)) {\n // Add new format - index is 1 + position in additionalFormats array\n formatToYAxisIndex.set(unitKey, 1 + additionalFormats.length);\n additionalFormats.push(qs.format);\n }\n }\n }\n\n return { additionalFormats, formatToYAxisIndex, seriesFormatMap };\n }, [format, querySettingsList]);\n\n const [selectedLegendItems, setSelectedLegendItems] = useState<SelectedLegendItemState>('ALL');\n const [legendSorting, setLegendSorting] = useState<NonNullable<LegendProps['tableProps']>['sorting']>();\n\n const { setTimeRange } = useTimeRange();\n\n const annotationsWithData = usePanelAnnotationsWithData(props.definition?.spec.annotations);\n\n const annotations: TimeSeriesAnnotation[] = useMemo(\n () => convertAnnotationToTimeSeriesAnnotation(annotationsWithData),\n [annotationsWithData],\n );\n\n // Populate series data based on query results\n const {\n timeScale,\n timeChartData,\n timeSeriesMapping,\n legendItems,\n seriesFormatMap: computedSeriesFormatMap,\n maxValuesByFormat,\n } = useMemo(() => {\n const timeScale = getCommonTimeScaleForQueries(queryResults);\n if (timeScale === undefined) {\n return {\n timeChartData: [],\n timeSeriesMapping: [],\n seriesFormatMap: new Map(),\n maxValuesByFormat: new Map<string, number>(),\n };\n }\n\n const legendItems: LegendItem[] = [];\n\n // Utilizes ECharts dataset so raw data is separate from series option style properties\n // https://apache.github.io/echarts-handbook/en/concepts/dataset/\n const timeChartData: TimeSeries[] = [];\n const timeSeriesMapping: TimeChartSeriesMapping = [];\n\n // Track max values for each format unit (used for dynamic Y axis offset calculation)\n const maxValuesByFormat = new Map<string, number>();\n\n // Index is counted across multiple queries which ensures the categorical color palette does not reset for every query\n let seriesIndex = 0;\n\n // Mapping of each set of query results to be ECharts option compatible\n // TODO: Look into performance optimizations and moving parts of mapping to the lower level chart\n for (let queryIndex = 0; queryIndex < queryResults.length; queryIndex++) {\n const result = queryResults[queryIndex];\n\n // Retrieve querySettings for this query, if exists.\n // queries & querySettings indices do not necessarily match, so we have to check the tail value of the $ref attribute\n let querySettings: QuerySettingsOptions | undefined;\n for (const item of querySettingsList ?? []) {\n if (item.queryIndex === queryIndex) {\n querySettings = item;\n // We don't break the loop here just in case there are multiple querySettings defined for the\n // same queryIndex, because in that case we want the last one to take precedence.\n }\n }\n\n if (result) {\n for (let i = 0; i < result.data.series.length; i++) {\n const timeSeries: TimeSeries | undefined = result.data.series[i];\n if (timeSeries === undefined) {\n return { timeChartData: [], timeSeriesMapping: [], legendItems: [] };\n }\n\n // Format is determined by seriesNameFormat in query spec\n const formattedSeriesName = timeSeries.formattedName ?? timeSeries.name;\n\n // Color is used for line, tooltip, and legend\n const seriesColor = getSeriesColor({\n // ECharts type for color is not always an array but it is always an array in ChartsProvider\n categoricalPalette: categoricalPalette as string[],\n visual,\n muiPrimaryColor: muiTheme.palette.primary.main,\n seriesName: formattedSeriesName,\n seriesIndex,\n querySettings: querySettings,\n queryHasMultipleResults: (queryResults[queryIndex]?.data?.series?.length ?? 0) > 1,\n });\n\n // We add a unique id for the chart to disambiguate items across charts\n // when there are multiple on the page.\n const seriesId = chartId + timeSeries.name + seriesIndex;\n\n const legendCalculations = legend?.values\n ? getCalculations(timeSeries.values, legend.values as CalculationType[])\n : undefined;\n\n // When we initially load the chart, we want to show all series, but\n // DO NOT want to visualy highlight all the items in the legend.\n const isSelectAll = selectedLegendItems === 'ALL';\n const isSelected = !isSelectAll && !!selectedLegendItems[seriesId];\n const showTimeSeries = isSelected || isSelectAll;\n\n if (showTimeSeries) {\n // Use timeChartData.length to ensure the data that is passed into the tooltip accounts for\n // which legend items are selected. This must happen before timeChartData.push to avoid an\n // off-by-one error, seriesIndex cannot be used since it's needed to cycle through palette\n const datasetIndex = timeChartData.length;\n\n // Determine yAxisIndex based on the query's format setting\n const queryFormat = querySettings?.format;\n const yAxisIndex = queryFormat?.unit ? (formatToYAxisIndex.get(queryFormat.unit) ?? 0) : 0;\n\n // Each series is stored as a separate dataset source.\n // https://apache.github.io/echarts-handbook/en/concepts/dataset/#how-to-reference-several-datasets\n timeSeriesMapping.push(\n getTimeSeries(\n seriesId,\n datasetIndex,\n formattedSeriesName,\n visual,\n timeScale,\n seriesColor,\n querySettings,\n yAxisIndex,\n ),\n );\n\n // Store the format for this series for tooltip formatting\n if (queryFormat) {\n seriesFormatMap.set(seriesId, queryFormat);\n\n // Track max value for this format unit (used for dynamic Y axis offset calculation)\n const unitKey = queryFormat.unit;\n if (unitKey) {\n const seriesMax = Math.max(...timeSeries.values.map((v) => Math.abs(v[1] ?? 0)));\n const currentMax = maxValuesByFormat.get(unitKey) ?? 0;\n if (seriesMax > currentMax) {\n maxValuesByFormat.set(unitKey, seriesMax);\n }\n }\n }\n\n // When negativeY is set on this query, negate the rendered values so the\n // series renders below the X axis. The original (positive) values are\n // preserved in `timeSeries.values` (used for legend calculations) and in\n // `queryResults` (used for CSV export).\n const baseValues: TimeSeriesValueTuple[] = getTimeSeriesValues(timeSeries, timeScale);\n const renderedValues: TimeSeriesValueTuple[] = querySettings?.negativeY\n ? baseValues.map((tuple: TimeSeriesValueTuple): TimeSeriesValueTuple => {\n const [t, v] = tuple;\n return [t, v === null ? null : -v];\n })\n : baseValues;\n\n timeChartData.push({\n name: formattedSeriesName,\n values: renderedValues,\n });\n }\n\n if (legend && legendItems) {\n legendItems.push({\n id: seriesId, // Avoids duplicate key console errors when there are duplicate series names\n label: formattedSeriesName,\n color: seriesColor,\n data: legendCalculations,\n });\n }\n\n // Used for repeating colors in Categorical palette\n seriesIndex++;\n }\n }\n }\n\n // map thresholds only if there is at least one time series to avoid displaying thresholds without any data\n if (thresholds && thresholds.steps && timeChartData.length > 0) {\n // Convert how thresholds are defined in the panel spec to valid ECharts 'line' series.\n // These are styled with predefined colors and a dashed style to look different than series from query results.\n // Regular series are used instead of markLines since thresholds currently show in our React TimeSeriesTooltip.\n const thresholdsColors = chartsTheme.thresholds;\n const defaultThresholdColor = thresholds.defaultColor ?? thresholdsColors.defaultColor;\n thresholds.steps.forEach((step: StepOptions, index: number) => {\n const stepPaletteColor = thresholdsColors.palette[index] ?? defaultThresholdColor;\n const thresholdLineColor = step.color ?? stepPaletteColor;\n const stepOption: StepOptions = {\n color: thresholdLineColor,\n value:\n // yAxis is passed here since it corresponds to dashboard JSON instead of the already converted ECharts yAxis\n thresholds.mode === 'percent'\n ? convertPercentThreshold(step.value, timeChartData, yAxis?.max, yAxis?.min)\n : step.value,\n };\n const thresholdName = step.name ?? `Threshold ${index + 1}`;\n\n // Generates array of [time, step.value] where time ranges from timescale.startMs to timescale.endMs with an interval of 15s\n const thresholdTimeValueTuple: TimeSeriesValueTuple[] = [];\n let currentTimestamp = timeScale.startMs;\n while (currentTimestamp <= timeScale.endMs) {\n thresholdTimeValueTuple.push([currentTimestamp, stepOption.value]);\n // Used to plot fake thresholds datapoints so correct nearby threshold series shows in tooltip without flicker\n currentTimestamp += 1000 * THRESHOLD_PLOT_INTERVAL;\n }\n\n timeChartData.push({\n name: thresholdName,\n values: thresholdTimeValueTuple,\n });\n timeSeriesMapping.push(getThresholdSeries(thresholdName, stepOption, seriesIndex));\n seriesIndex++;\n });\n }\n\n return {\n timeScale,\n timeChartData,\n timeSeriesMapping,\n legendItems,\n seriesFormatMap,\n maxValuesByFormat,\n };\n }, [\n queryResults,\n thresholds,\n selectedLegendItems,\n legend,\n visual,\n querySettingsList,\n yAxis?.max,\n yAxis?.min,\n categoricalPalette,\n chartId,\n chartsTheme.thresholds,\n muiTheme.palette.primary.main,\n formatToYAxisIndex,\n seriesFormatMap,\n ]);\n\n // Create multiple Y axes if there are additional formats\n // Uses max values from data to compute dynamic offsets that adapt to label widths\n const multipleYAxes = useMemo(() => {\n if (additionalFormats.length === 0) {\n return undefined; // Use single Y axis (default behavior)\n }\n // Build array of max values for each additional format (in order)\n const maxValues = additionalFormats.map((fmt) => {\n const unitKey = fmt.unit;\n return unitKey ? (maxValuesByFormat?.get(unitKey) ?? 1000) : 1000;\n });\n return getFormattedMultipleYAxes(echartsYAxis, format, additionalFormats, maxValues);\n }, [echartsYAxis, format, additionalFormats, maxValuesByFormat]);\n\n // Translate the legend values into columns for the table legend.\n const legendColumns = useMemo(() => {\n if (!legend?.values) {\n return [];\n }\n\n // Iterating the predefined list of possible values to retain a specific\n // intended order of values.\n return legendValues.reduce(\n (columns, legendValue) => {\n const legendConfig = LEGEND_VALUE_CONFIG[legendValue];\n\n if (legendConfig && legend?.values?.includes(legendValue)) {\n columns.push({\n accessorKey: `data.${legendValue}`,\n header: legendConfig.label,\n headerDescription: legendConfig.description,\n // Intentionally hardcoding a column width to start based on discussions\n // with design around keeping this simple to start. This may need\n // revisiting in the future to handle edge cases with very large values.\n width: 72,\n align: 'right',\n cell: ({ getValue }) => {\n const cellValue = getValue();\n return typeof cellValue === 'number' && format ? formatValue(cellValue, format) : cellValue;\n },\n cellDescription: true,\n enableSorting: true,\n });\n }\n\n return columns;\n },\n [] as Array<TableColumnConfig<LegendItem>>,\n );\n }, [legend?.values, format]);\n\n const gridOverrides: GridComponentOption = useMemo(() => {\n // When Y axes are hidden, disable containLabel to prevent auto-spacing, but add bottom padding for X axis\n return echartsYAxis.show === false\n ? {\n left: 0,\n right: 0,\n bottom: 30,\n containLabel: false,\n }\n : {\n left: yAxis && yAxis.label ? 30 : 20,\n // With containLabel: true in theme, ECharts auto-reserves space for axis labels.\n // For multiple right axes, add extra padding for the last axis labels that extend beyond the grid.\n right: additionalFormats.length > 0 ? 10 : 20,\n bottom: 0,\n containLabel: true,\n };\n }, [echartsYAxis.show, yAxis, additionalFormats.length]);\n\n if (adjustedContentDimensions === undefined) {\n return null;\n }\n\n const handleDataZoom = (event: ZoomEventData): void => {\n // TODO: add ECharts transition animation on zoom\n setTimeRange({ start: new Date(event.start), end: new Date(event.end) });\n };\n\n // Used to opt in to ECharts trigger item which show subgroup data accurately.\n // Derived from the actual series mapping rather than `visual.stack` alone so that\n // bar charts stacked only via per-query overrides also use the right tooltip mode.\n const isStackedBar =\n visual.display === 'bar' && timeSeriesMapping.some((s) => s?.type === 'bar' && s.stack === 'all');\n\n // Turn on tooltip pinning by default but opt out for stacked bar or if explicitly set in tooltip panel spec\n let enablePinning = true;\n if (isStackedBar) {\n enablePinning = false;\n } else if (tooltip?.enablePinning !== undefined) {\n enablePinning = tooltip.enablePinning;\n }\n const tooltipConfig: TooltipConfig = {\n ...DEFAULT_TOOLTIP_CONFIG,\n enablePinning,\n };\n\n return (\n <Box sx={{ padding: `${contentPadding}px` }}>\n <ContentWithLegend\n width={adjustedContentDimensions.width}\n height={adjustedContentDimensions.height}\n // Making this small enough that the medium size doesn't get\n // responsive-handling-ed away when in the panel options editor.\n minChildrenHeight={50}\n legendSize={legend?.size}\n legendProps={\n legend && {\n options: legend,\n data: legendItems || [],\n selectedItems: selectedLegendItems,\n onSelectedItemsChange: setSelectedLegendItems,\n tableProps: {\n columns: legendColumns,\n sorting: legendSorting,\n onSortingChange: setLegendSorting,\n },\n onItemMouseOver: (e, { id }): void => {\n chartRef.current?.highlightSeries({ name: id });\n },\n onItemMouseOut: (): void => {\n chartRef.current?.clearHighlightedSeries();\n },\n }\n }\n >\n {({ height, width }) => {\n return (\n <Box style={{ height, width }}>\n {yAxis && yAxis.show && yAxis.label && <YAxisLabel name={yAxis.label} height={height} />}\n <TimeSeriesChartBase\n ref={chartRef}\n height={height}\n data={timeChartData}\n seriesMapping={timeSeriesMapping}\n annotations={annotations}\n timeScale={timeScale}\n yAxis={multipleYAxes ?? echartsYAxis}\n format={format}\n seriesFormatMap={computedSeriesFormatMap}\n grid={gridOverrides}\n isStackedBar={isStackedBar}\n tooltipConfig={tooltipConfig}\n syncGroup=\"default-panel-group\" // TODO: make configurable from dashboard settings and per panel-group overrides\n onDataZoom={handleDataZoom}\n // Show an empty chart when there is no data because the user unselected all items in\n // the legend. Otherwise, show a \"no data\" message.\n noDataVariant={!timeChartData.length && legendItems && legendItems.length > 0 ? 'chart' : 'message'}\n />\n </Box>\n );\n }}\n </ContentWithLegend>\n </Box>\n );\n}\n"],"names":["Box","useTheme","YAxisLabel","useChartsTheme","ContentWithLegend","useId","DEFAULT_TOOLTIP_CONFIG","getFormattedMultipleYAxes","DEFAULT_LEGEND","formatValue","getTimeSeriesValues","usePanelAnnotationsWithData","LEGEND_VALUE_CONFIG","useTimeRange","validateLegendSpec","legendValues","getCalculations","merge","useMemo","useRef","useState","DEFAULT_FORMAT","DEFAULT_VISUAL","THRESHOLD_PLOT_INTERVAL","TimeSeriesChartBase","convertAnnotationToTimeSeriesAnnotation","getTimeSeries","getCommonTimeScaleForQueries","convertPanelYAxis","getThresholdSeries","convertPercentThreshold","getSeriesColor","TimeSeriesChartPanel","props","spec","thresholds","yAxis","tooltip","querySettings","querySettingsList","contentDimensions","queryResults","chartsTheme","muiTheme","chartId","chartRef","categoricalPalette","echartsTheme","color","contentPadding","container","padding","default","adjustedContentDimensions","width","height","undefined","legend","format","visual","echartsYAxis","additionalFormats","formatToYAxisIndex","seriesFormatMap","baseUnit","unit","Map","set","qs","unitKey","has","length","push","selectedLegendItems","setSelectedLegendItems","legendSorting","setLegendSorting","setTimeRange","annotationsWithData","definition","annotations","timeScale","timeChartData","timeSeriesMapping","legendItems","computedSeriesFormatMap","maxValuesByFormat","seriesIndex","queryIndex","result","item","i","data","series","timeSeries","formattedSeriesName","formattedName","name","seriesColor","muiPrimaryColor","palette","primary","main","seriesName","queryHasMultipleResults","seriesId","legendCalculations","values","isSelectAll","isSelected","showTimeSeries","datasetIndex","queryFormat","yAxisIndex","get","seriesMax","Math","max","map","v","abs","currentMax","baseValues","renderedValues","negativeY","tuple","t","id","label","steps","thresholdsColors","defaultThresholdColor","defaultColor","forEach","step","index","stepPaletteColor","thresholdLineColor","stepOption","value","mode","min","thresholdName","thresholdTimeValueTuple","currentTimestamp","startMs","endMs","multipleYAxes","maxValues","fmt","legendColumns","reduce","columns","legendValue","legendConfig","includes","accessorKey","header","headerDescription","description","align","cell","getValue","cellValue","cellDescription","enableSorting","gridOverrides","show","left","right","bottom","containLabel","handleDataZoom","event","start","Date","end","isStackedBar","display","some","s","type","stack","enablePinning","tooltipConfig","sx","minChildrenHeight","legendSize","size","legendProps","options","selectedItems","onSelectedItemsChange","tableProps","sorting","onSortingChange","onItemMouseOver","e","current","highlightSeries","onItemMouseOut","clearHighlightedSeries","style","ref","seriesMapping","grid","syncGroup","onDataZoom","noDataVariant"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/TimeSeriesChartPanel.tsx"],"sourcesContent":["// Copyright 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 { Box, useTheme } from '@mui/material';\nimport type {\n ChartInstance,\n ZoomEventData,\n SelectedLegendItemState,\n TableColumnConfig,\n LegendItem,\n LegendProps,\n TooltipConfig,\n TimeChartSeriesMapping,\n StepOptions,\n} from '@perses-dev/components';\nimport {\n YAxisLabel,\n useChartsTheme,\n ContentWithLegend,\n useId,\n DEFAULT_TOOLTIP_CONFIG,\n getFormattedMultipleYAxes,\n DEFAULT_LEGEND,\n formatValue,\n getTimeSeriesValues,\n} from '@perses-dev/components';\nimport { usePanelAnnotationsWithData } from '@perses-dev/dashboards';\nimport type { PanelProps, CalculationType } from '@perses-dev/plugin-system';\nimport {\n LEGEND_VALUE_CONFIG,\n useTimeRange,\n validateLegendSpec,\n legendValues,\n getCalculations,\n} from '@perses-dev/plugin-system';\nimport type { Labels, TimeSeries, TimeSeriesData, TimeSeriesValueTuple } from '@perses-dev/spec';\nimport type { GridComponentOption } from 'echarts';\nimport merge from 'lodash/merge';\nimport type { ReactElement } from 'react';\nimport { memo, useCallback, useMemo, useRef, useState } from 'react';\n\nimport type { TimeSeriesChartOptions } from './time-series-chart-model';\nimport { DEFAULT_FORMAT, DEFAULT_VISUAL, THRESHOLD_PLOT_INTERVAL } from './time-series-chart-model';\nimport { TimeSeriesChartBase } from './TimeSeriesChartBase';\nimport type { TimeSeriesAnnotation } from './utils/annotation';\nimport { convertAnnotationToTimeSeriesAnnotation } from './utils/annotation';\nimport type { ExemplarChartData } from './utils/data-transform';\nimport {\n getTimeSeries,\n getCommonTimeScaleForQueries,\n convertPanelYAxis,\n getThresholdSeries,\n convertPercentThreshold,\n} from './utils/data-transform';\nimport { getSeriesColor } from './utils/palette-gen';\n\nexport type TimeSeriesChartProps = PanelProps<TimeSeriesChartOptions, TimeSeriesData>;\n\n/**\n * Stable string key for a labels record, so exemplars can be matched to their\n * series regardless of the labels order.\n */\nfunction labelsKey(labels: Labels): string {\n return JSON.stringify(\n Object.keys(labels)\n .toSorted()\n .map((labelName) => [labelName, labels[labelName]]),\n );\n}\n\n// Using an \"ALL\" value to handle the case on first loading the chart where we\n// want to select all, but do not want all of the legend items to be visually highlighted.\n// This helps us differentiate those cases more clearly instead of inferring it\n// based on the state of the data. This also helps us avoid some coding\n// complexity around initializing a full record for the initial load that would\n// currently require significantly more refactoring of this component.\n// TODO: simplify this if we switch the list-based legend UI to use checkboxes,\n// where we *would* want to visually select all items in this case.\n\nfunction TimeSeriesChartPanelComponent(props: TimeSeriesChartProps): ReactElement | null {\n const {\n spec: { thresholds, yAxis, tooltip, querySettings: querySettingsList },\n contentDimensions,\n queryResults,\n } = props;\n const chartsTheme = useChartsTheme();\n const muiTheme = useTheme();\n const chartId = useId('time-series-panel');\n\n const chartRef = useRef<ChartInstance>(null);\n\n // ECharts theme comes from ChartsProvider, more info: https://echarts.apache.org/en/option.html#color\n // Colors are manually applied since our legend and tooltip are built custom with React.\n const categoricalPalette = chartsTheme.echartsTheme.color;\n\n // TODO: consider refactoring how the layout/spacing/alignment are calculated\n // the next time significant changes are made to the time series panel (e.g.\n // when making improvements to the legend to more closely match designs).\n // This may also want to include moving some of this logic down to the shared,\n // embeddable components.\n const contentPadding = chartsTheme.container.padding.default;\n const adjustedContentDimensions: typeof contentDimensions = contentDimensions\n ? {\n width: contentDimensions.width - contentPadding * 2,\n height: contentDimensions.height - contentPadding * 2,\n }\n : undefined;\n\n // populate default 'position' and other future properties\n const legend = useMemo(() => {\n return props.spec.legend && validateLegendSpec(props.spec.legend)\n ? merge({}, DEFAULT_LEGEND, props.spec.legend)\n : undefined;\n }, [props.spec.legend]);\n\n // TODO: add support for y_axis_alt.format\n const format = props.spec.yAxis?.format ?? DEFAULT_FORMAT;\n\n // ensures there are fallbacks for unset properties since most\n // users should not need to customize visual display\n const visual = useMemo(() => {\n return merge({}, DEFAULT_VISUAL, props.spec.visual);\n }, [props.spec.visual]);\n\n // convert Perses dashboard format to be ECharts compatible\n const echartsYAxis = useMemo(() => {\n return convertPanelYAxis(yAxis);\n }, [yAxis]);\n\n // Collect unique formats from query settings that differ from the base format\n // These will create additional Y axes on the right side\n const { additionalFormats, formatToYAxisIndex } = useMemo(() => {\n const baseUnit = format?.unit ?? 'decimal';\n const additionalFormats: Array<typeof format> = [];\n const formatToYAxisIndex = new Map<string, number>();\n\n // Index 0 is reserved for the base Y axis\n formatToYAxisIndex.set(baseUnit, 0);\n\n // Collect unique formats from query settings\n for (const qs of querySettingsList ?? []) {\n if (qs.format?.unit && qs.format.unit !== baseUnit) {\n const unitKey = qs.format.unit;\n if (!formatToYAxisIndex.has(unitKey)) {\n // Add new format - index is 1 + position in additionalFormats array\n formatToYAxisIndex.set(unitKey, 1 + additionalFormats.length);\n additionalFormats.push(qs.format);\n }\n }\n }\n\n return { additionalFormats, formatToYAxisIndex };\n }, [format, querySettingsList]);\n\n const [selectedLegendItems, setSelectedLegendItems] = useState<SelectedLegendItemState>('ALL');\n const [legendSorting, setLegendSorting] = useState<NonNullable<LegendProps['tableProps']>['sorting']>();\n\n const { setTimeRange } = useTimeRange();\n\n const annotationsWithData = usePanelAnnotationsWithData(props.definition?.spec.annotations);\n\n const annotations: TimeSeriesAnnotation[] = useMemo(\n () => convertAnnotationToTimeSeriesAnnotation(annotationsWithData),\n [annotationsWithData],\n );\n\n const calculationTypes = legend?.values;\n\n // Point processing and legend statistics depend on query data, not legend selection.\n // Reuse these arrays when toggling series instead of rescanning every sample.\n const { timeScale, preparedQueries } = useMemo(() => {\n const commonScale = getCommonTimeScaleForQueries(queryResults);\n const settingsByQuery = new Map(querySettingsList?.map((settings) => [settings.queryIndex, settings]));\n let seriesIndex = 0;\n const queries = commonScale\n ? queryResults.map((result, queryIndex) => {\n const querySettings = settingsByQuery.get(queryIndex);\n const series = result.data.series.map((timeSeries) => {\n const baseValues = getTimeSeriesValues(timeSeries, commonScale);\n const values = querySettings?.negativeY\n ? baseValues.map(([t, v]): TimeSeriesValueTuple => [t, v === null ? null : -v])\n : baseValues;\n const calculations = calculationTypes\n ? getCalculations(timeSeries.values, calculationTypes as CalculationType[])\n : undefined;\n let maxValue = 0;\n if (querySettings?.format?.unit) {\n for (const [, value] of timeSeries.values) {\n maxValue = Math.max(maxValue, Math.abs(value ?? 0));\n }\n }\n const seriesId = `${chartId}${timeSeries.name}${seriesIndex}`;\n seriesIndex += 1;\n return { timeSeries, seriesId, values, calculations, maxValue };\n });\n return { querySettings, series, exemplars: result.data.exemplars };\n })\n : [];\n return { timeScale: commonScale, preparedQueries: queries };\n }, [queryResults, querySettingsList, calculationTypes, chartId]);\n\n // Prepare all exemplar groups independently of legend selection. The base chart\n // filters their scatter series without rebuilding marker data for visible groups.\n const chartExemplars = useMemo(() => {\n const groups: ExemplarChartData[] = [];\n let seriesIndex = 0;\n for (const { querySettings, series, exemplars } of preparedQueries) {\n // Labels identify a series within a query, not across different queries.\n const seriesByLabels = new Map<string, ExemplarChartData>();\n for (const { timeSeries, seriesId } of series) {\n const seriesName = timeSeries.formattedName ?? timeSeries.name;\n if (exemplars?.length && timeSeries.labels) {\n seriesByLabels.set(labelsKey(timeSeries.labels), {\n seriesId,\n seriesName,\n color: getSeriesColor({\n categoricalPalette: categoricalPalette as string[],\n visual,\n muiPrimaryColor: muiTheme.palette.primary.main,\n seriesName,\n seriesIndex,\n querySettings,\n queryHasMultipleResults: series.length > 1,\n }),\n seriesLabels: timeSeries.labels,\n yAxisIndex: formatToYAxisIndex.get(querySettings?.format?.unit ?? '') ?? 0,\n negativeY: querySettings?.negativeY,\n exemplars: [],\n });\n }\n seriesIndex++;\n }\n for (const group of exemplars ?? []) {\n if (group.exemplars.length === 0) continue;\n const matched = seriesByLabels.get(labelsKey(group.seriesLabels));\n if (matched) groups.push({ ...matched, exemplars: group.exemplars });\n }\n }\n return groups;\n }, [preparedQueries, categoricalPalette, visual, muiTheme.palette.primary.main, formatToYAxisIndex]);\n\n // Populate series data based on query results\n const {\n timeChartData,\n timeSeriesMapping,\n legendItems,\n seriesFormatMap: computedSeriesFormatMap,\n maxValuesByFormat,\n } = useMemo(() => {\n if (timeScale === undefined) {\n return {\n timeChartData: [] as TimeSeries[],\n timeSeriesMapping: [] as TimeChartSeriesMapping,\n legendItems: [] as LegendItem[],\n seriesFormatMap: new Map(),\n maxValuesByFormat: new Map<string, number>(),\n };\n }\n\n const legendItems: LegendItem[] = [];\n\n // Utilizes ECharts dataset so raw data is separate from series option style properties\n // https://apache.github.io/echarts-handbook/en/concepts/dataset/\n const timeChartData: TimeSeries[] = [];\n const timeSeriesMapping: TimeChartSeriesMapping = [];\n\n // Track max values for each format unit (used for dynamic Y axis offset calculation)\n const maxValuesByFormat = new Map<string, number>();\n const seriesFormatMap = new Map<string, typeof format>();\n\n let visibleSeriesCount = 0;\n for (const { series } of preparedQueries) {\n for (const { seriesId } of series) {\n if (selectedLegendItems === 'ALL' || selectedLegendItems[seriesId]) visibleSeriesCount++;\n }\n }\n\n // Index is counted across multiple queries which ensures the categorical color palette does not reset for every query\n let seriesIndex = 0;\n\n for (const { querySettings, series } of preparedQueries) {\n for (const { timeSeries, seriesId, values, calculations, maxValue } of series) {\n // Format is determined by seriesNameFormat in query spec\n const formattedSeriesName = timeSeries.formattedName ?? timeSeries.name;\n\n // Color is used for line, tooltip, and legend\n const seriesColor = getSeriesColor({\n // ECharts type for color is not always an array but it is always an array in ChartsProvider\n categoricalPalette: categoricalPalette as string[],\n visual,\n muiPrimaryColor: muiTheme.palette.primary.main,\n seriesName: formattedSeriesName,\n seriesIndex,\n querySettings: querySettings,\n queryHasMultipleResults: series.length > 1,\n });\n\n // When we initially load the chart, we want to show all series, but\n // DO NOT want to visualy highlight all the items in the legend.\n const isSelectAll = selectedLegendItems === 'ALL';\n const isSelected = !isSelectAll && !!selectedLegendItems[seriesId];\n const showTimeSeries = isSelected || isSelectAll;\n\n if (showTimeSeries) {\n // Use timeChartData.length to ensure the data that is passed into the tooltip accounts for\n // which legend items are selected. This must happen before timeChartData.push to avoid an\n // off-by-one error, seriesIndex cannot be used since it's needed to cycle through palette\n const datasetIndex = timeChartData.length;\n\n // Determine yAxisIndex based on the query's format setting\n const queryFormat = querySettings?.format;\n const yAxisIndex = queryFormat?.unit ? (formatToYAxisIndex.get(queryFormat.unit) ?? 0) : 0;\n\n // Each series is stored as a separate dataset source.\n // https://apache.github.io/echarts-handbook/en/concepts/dataset/#how-to-reference-several-datasets\n timeSeriesMapping.push(\n getTimeSeries(\n seriesId,\n datasetIndex,\n formattedSeriesName,\n visual,\n timeScale,\n seriesColor,\n querySettings,\n yAxisIndex,\n visibleSeriesCount,\n ),\n );\n\n // Store the format for this series for tooltip formatting\n if (queryFormat) {\n seriesFormatMap.set(seriesId, queryFormat);\n\n // Track max value for this format unit (used for dynamic Y axis offset calculation)\n const unitKey = queryFormat.unit;\n if (unitKey) {\n const currentMax = maxValuesByFormat.get(unitKey) ?? 0;\n if (maxValue > currentMax) {\n maxValuesByFormat.set(unitKey, maxValue);\n }\n }\n }\n\n timeChartData.push({\n name: formattedSeriesName,\n values,\n });\n }\n\n if (legend && legendItems) {\n legendItems.push({\n id: seriesId, // Avoids duplicate key console errors when there are duplicate series names\n label: formattedSeriesName,\n color: seriesColor,\n data: calculations,\n });\n }\n\n // Used for repeating colors in Categorical palette\n seriesIndex += 1;\n }\n }\n\n // map thresholds only if there is at least one time series to avoid displaying thresholds without any data\n if (thresholds && thresholds.steps && timeChartData.length > 0) {\n // Convert how thresholds are defined in the panel spec to valid ECharts 'line' series.\n // These are styled with predefined colors and a dashed style to look different than series from query results.\n // Regular series are used instead of markLines since thresholds currently show in our React TimeSeriesTooltip.\n const thresholdsColors = chartsTheme.thresholds;\n const defaultThresholdColor = thresholds.defaultColor ?? thresholdsColors.defaultColor;\n thresholds.steps.forEach((step: StepOptions, index: number) => {\n const stepPaletteColor = thresholdsColors.palette[index] ?? defaultThresholdColor;\n const thresholdLineColor = step.color ?? stepPaletteColor;\n const stepOption: StepOptions = {\n color: thresholdLineColor,\n value:\n // yAxis is passed here since it corresponds to dashboard JSON instead of the already converted ECharts yAxis\n thresholds.mode === 'percent'\n ? convertPercentThreshold(step.value, timeChartData, yAxis?.max, yAxis?.min)\n : step.value,\n };\n const thresholdName = step.name ?? `Threshold ${index + 1}`;\n\n // Generates array of [time, step.value] where time ranges from timescale.startMs to timescale.endMs with an interval of 15s\n const thresholdTimeValueTuple: TimeSeriesValueTuple[] = [];\n let currentTimestamp = timeScale.startMs;\n while (currentTimestamp <= timeScale.endMs) {\n thresholdTimeValueTuple.push([currentTimestamp, stepOption.value]);\n // Used to plot fake thresholds datapoints so correct nearby threshold series shows in tooltip without flicker\n currentTimestamp += 1000 * THRESHOLD_PLOT_INTERVAL;\n }\n\n timeChartData.push({\n name: thresholdName,\n values: thresholdTimeValueTuple,\n });\n timeSeriesMapping.push(getThresholdSeries(thresholdName, stepOption, seriesIndex));\n seriesIndex++;\n });\n }\n\n return {\n timeScale,\n timeChartData,\n timeSeriesMapping,\n legendItems,\n seriesFormatMap,\n maxValuesByFormat,\n };\n }, [\n preparedQueries,\n timeScale,\n thresholds,\n selectedLegendItems,\n legend,\n visual,\n yAxis?.max,\n yAxis?.min,\n categoricalPalette,\n chartsTheme.thresholds,\n muiTheme.palette.primary.main,\n formatToYAxisIndex,\n ]);\n\n // Create multiple Y axes if there are additional formats\n // Uses max values from data to compute dynamic offsets that adapt to label widths\n const multipleYAxes = useMemo(() => {\n if (additionalFormats.length === 0) {\n return undefined; // Use single Y axis (default behavior)\n }\n // Build array of max values for each additional format (in order)\n const maxValues = additionalFormats.map((fmt) => {\n const unitKey = fmt.unit;\n return unitKey ? (maxValuesByFormat?.get(unitKey) ?? 1000) : 1000;\n });\n return getFormattedMultipleYAxes(echartsYAxis, format, additionalFormats, maxValues);\n }, [echartsYAxis, format, additionalFormats, maxValuesByFormat]);\n\n // Translate the legend values into columns for the table legend.\n const legendColumns = useMemo(() => {\n if (!legend?.values) {\n return [];\n }\n\n // Iterating the predefined list of possible values to retain a specific\n // intended order of values.\n return legendValues.reduce(\n (columns, legendValue) => {\n const legendConfig = LEGEND_VALUE_CONFIG[legendValue];\n\n if (legendConfig && legend?.values?.includes(legendValue)) {\n columns.push({\n accessorKey: `data.${legendValue}`,\n header: legendConfig.label,\n headerDescription: legendConfig.description,\n // Intentionally hardcoding a column width to start based on discussions\n // with design around keeping this simple to start. This may need\n // revisiting in the future to handle edge cases with very large values.\n width: 72,\n align: 'right',\n cell: ({ getValue }) => {\n const cellValue = getValue();\n return typeof cellValue === 'number' && format ? formatValue(cellValue, format) : cellValue;\n },\n cellDescription: true,\n enableSorting: true,\n });\n }\n\n return columns;\n },\n [] as Array<TableColumnConfig<LegendItem>>,\n );\n }, [legend?.values, format]);\n\n const gridOverrides: GridComponentOption = useMemo(() => {\n // When Y axes are hidden, disable containLabel to prevent auto-spacing, but add bottom padding for X axis\n return echartsYAxis.show === false\n ? {\n left: 0,\n right: 0,\n bottom: 30,\n containLabel: false,\n }\n : {\n left: yAxis && yAxis.label ? 30 : 20,\n // With containLabel: true in theme, ECharts auto-reserves space for axis labels.\n // For multiple right axes, add extra padding for the last axis labels that extend beyond the grid.\n right: additionalFormats.length > 0 ? 10 : 20,\n bottom: 0,\n containLabel: true,\n };\n }, [echartsYAxis.show, yAxis, additionalFormats.length]);\n\n const handleDataZoom = useCallback(\n (event: ZoomEventData): void => {\n setTimeRange({ start: new Date(event.start), end: new Date(event.end) });\n },\n [setTimeRange],\n );\n\n if (adjustedContentDimensions === undefined) {\n return null;\n }\n\n // Used to opt in to ECharts trigger item which show subgroup data accurately.\n // Derived from the actual series mapping rather than `visual.stack` alone so that\n // bar charts stacked only via per-query overrides also use the right tooltip mode.\n const isStackedBar =\n visual.display === 'bar' && timeSeriesMapping.some((s) => s?.type === 'bar' && s.stack === 'all');\n\n // Turn on tooltip pinning by default but opt out for stacked bar or if explicitly set in tooltip panel spec\n let enablePinning = true;\n if (isStackedBar) {\n enablePinning = false;\n } else if (tooltip?.enablePinning !== undefined) {\n enablePinning = tooltip.enablePinning;\n }\n const tooltipConfig: TooltipConfig = {\n ...DEFAULT_TOOLTIP_CONFIG,\n enablePinning,\n };\n\n return (\n <Box sx={{ padding: `${contentPadding}px` }}>\n <ContentWithLegend\n width={adjustedContentDimensions.width}\n height={adjustedContentDimensions.height}\n // Making this small enough that the medium size doesn't get\n // responsive-handling-ed away when in the panel options editor.\n minChildrenHeight={50}\n legendSize={legend?.size}\n legendProps={\n legend && {\n options: legend,\n data: legendItems || [],\n selectedItems: selectedLegendItems,\n onSelectedItemsChange: setSelectedLegendItems,\n tableProps: {\n columns: legendColumns,\n sorting: legendSorting,\n onSortingChange: setLegendSorting,\n },\n onItemMouseOver: (e, { id }): void => {\n chartRef.current?.highlightSeries({ name: id });\n },\n onItemMouseOut: (): void => {\n chartRef.current?.clearHighlightedSeries();\n },\n }\n }\n >\n {({ height, width }) => {\n return (\n <Box style={{ height, width }}>\n {yAxis && yAxis.show && yAxis.label && <YAxisLabel name={yAxis.label} height={height} />}\n <TimeSeriesChartBase\n ref={chartRef}\n height={height}\n data={timeChartData}\n seriesMapping={timeSeriesMapping}\n exemplars={chartExemplars}\n annotations={annotations}\n timeScale={timeScale}\n yAxis={multipleYAxes ?? echartsYAxis}\n format={format}\n seriesFormatMap={computedSeriesFormatMap}\n grid={gridOverrides}\n isStackedBar={isStackedBar}\n tooltipConfig={tooltipConfig}\n syncGroup=\"default-panel-group\" // TODO: make configurable from dashboard settings and per panel-group overrides\n onDataZoom={handleDataZoom}\n // Show an empty chart when there is no data because the user unselected all items in\n // the legend. Otherwise, show a \"no data\" message.\n noDataVariant={!timeChartData.length && legendItems && legendItems.length > 0 ? 'chart' : 'message'}\n />\n </Box>\n );\n }}\n </ContentWithLegend>\n </Box>\n );\n}\n\n// PanelContent recreates the queryResults array and its wrappers on dashboard\n// hover/focus updates. Compare the underlying references in query order so those\n// updates do not invalidate data preparation or scan the samples and exemplars.\nexport const TimeSeriesChartPanel = memo(\n TimeSeriesChartPanelComponent,\n (previous, next): boolean =>\n previous.spec === next.spec &&\n previous.definition === next.definition &&\n previous.contentDimensions?.width === next.contentDimensions?.width &&\n previous.contentDimensions?.height === next.contentDimensions?.height &&\n previous.queryResults.length === next.queryResults.length &&\n previous.queryResults.every(\n (query, index) =>\n query.data === next.queryResults[index]?.data && query.definition === next.queryResults[index]?.definition,\n ),\n);\n"],"names":["Box","useTheme","YAxisLabel","useChartsTheme","ContentWithLegend","useId","DEFAULT_TOOLTIP_CONFIG","getFormattedMultipleYAxes","DEFAULT_LEGEND","formatValue","getTimeSeriesValues","usePanelAnnotationsWithData","LEGEND_VALUE_CONFIG","useTimeRange","validateLegendSpec","legendValues","getCalculations","merge","memo","useCallback","useMemo","useRef","useState","DEFAULT_FORMAT","DEFAULT_VISUAL","THRESHOLD_PLOT_INTERVAL","TimeSeriesChartBase","convertAnnotationToTimeSeriesAnnotation","getTimeSeries","getCommonTimeScaleForQueries","convertPanelYAxis","getThresholdSeries","convertPercentThreshold","getSeriesColor","labelsKey","labels","JSON","stringify","Object","keys","toSorted","map","labelName","TimeSeriesChartPanelComponent","props","spec","thresholds","yAxis","tooltip","querySettings","querySettingsList","contentDimensions","queryResults","chartsTheme","muiTheme","chartId","chartRef","categoricalPalette","echartsTheme","color","contentPadding","container","padding","default","adjustedContentDimensions","width","height","undefined","legend","format","visual","echartsYAxis","additionalFormats","formatToYAxisIndex","baseUnit","unit","Map","set","qs","unitKey","has","length","push","selectedLegendItems","setSelectedLegendItems","legendSorting","setLegendSorting","setTimeRange","annotationsWithData","definition","annotations","calculationTypes","values","timeScale","preparedQueries","commonScale","settingsByQuery","settings","queryIndex","seriesIndex","queries","result","get","series","data","timeSeries","baseValues","negativeY","t","v","calculations","maxValue","value","Math","max","abs","seriesId","name","exemplars","chartExemplars","groups","seriesByLabels","seriesName","formattedName","muiPrimaryColor","palette","primary","main","queryHasMultipleResults","seriesLabels","yAxisIndex","group","matched","timeChartData","timeSeriesMapping","legendItems","seriesFormatMap","computedSeriesFormatMap","maxValuesByFormat","visibleSeriesCount","formattedSeriesName","seriesColor","isSelectAll","isSelected","showTimeSeries","datasetIndex","queryFormat","currentMax","id","label","steps","thresholdsColors","defaultThresholdColor","defaultColor","forEach","step","index","stepPaletteColor","thresholdLineColor","stepOption","mode","min","thresholdName","thresholdTimeValueTuple","currentTimestamp","startMs","endMs","multipleYAxes","maxValues","fmt","legendColumns","reduce","columns","legendValue","legendConfig","includes","accessorKey","header","headerDescription","description","align","cell","getValue","cellValue","cellDescription","enableSorting","gridOverrides","show","left","right","bottom","containLabel","handleDataZoom","event","start","Date","end","isStackedBar","display","some","s","type","stack","enablePinning","tooltipConfig","sx","minChildrenHeight","legendSize","size","legendProps","options","selectedItems","onSelectedItemsChange","tableProps","sorting","onSortingChange","onItemMouseOver","e","current","highlightSeries","onItemMouseOut","clearHighlightedSeries","style","ref","seriesMapping","grid","syncGroup","onDataZoom","noDataVariant","TimeSeriesChartPanel","previous","next","every","query"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import type { TimeSeriesData } from '@perses-dev/spec';
1
+ import type { TimeSeriesData, TimeSeriesExemplars } from '@perses-dev/spec';
2
2
  export declare const MOCK_TIME_SERIES_QUERY_RESULT_MULTIVALUE: {
3
3
  status: string;
4
4
  fetchStatus: string;
@@ -82,6 +82,7 @@ export declare const MOCK_TIME_SERIES_QUERY_RESULT_SINGLEVALUE: {
82
82
  isStale: boolean;
83
83
  }[];
84
84
  export declare const MOCK_TIME_SERIES_DATA_MULTIVALUE: TimeSeriesData;
85
+ export declare const MOCK_TIME_SERIES_EXEMPLARS: TimeSeriesExemplars[];
85
86
  export declare const MOCK_TIME_SERIES_DATA_SINGLEVALUE: TimeSeriesData;
86
87
  export declare const MOCK_NULL_QUERY_RESULT: {
87
88
  status: string;
@@ -1 +1 @@
1
- {"version":3,"file":"mock-query-results.d.ts","sourceRoot":"","sources":["../../../src/test/mock-query-results.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEvD,eAAO,MAAM,wCAAwC;;;;;;;;YAS7C,KAAK;YACL,GAAG;;;;;;;gBAWC,MAAM;gBACN,GAAG;gBACH,MAAM;gBACN,QAAQ;gBACR,GAAG;gBACH,UAAU;;;;;;;;;;;;;;;;;;;GAoCrB,CAAC;AAEF,eAAO,MAAM,yCAAyC;;;;;;;;YAS9C,KAAK;YACL,GAAG;;;;;;;gBAQC,MAAM;gBACN,GAAG;gBACH,MAAM;gBACN,QAAQ;gBACR,GAAG;gBACH,UAAU;;;;;;;;;;;;;;;;;;;GAiCrB,CAAC;AAEF,eAAO,MAAM,gCAAgC,EAAE,cAsC9C,CAAC;AAEF,eAAO,MAAM,iCAAiC,EAAE,cAgC/C,CAAC;AAEF,eAAO,MAAM,sBAAsB;;;;;;;;YAS3B,KAAK;YACL,GAAG;;;;;;;;gBA+BC,GAAG;gBACH,QAAQ;gBACR,GAAG;;;;;;;;;;;;;;;;;;;GAqBd,CAAC"}
1
+ {"version":3,"file":"mock-query-results.d.ts","sourceRoot":"","sources":["../../../src/test/mock-query-results.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAE5E,eAAO,MAAM,wCAAwC;;;;;;;;YAS7C,KAAK;YACL,GAAG;;;;;;;gBAWC,MAAM;gBACN,GAAG;gBACH,MAAM;gBACN,QAAQ;gBACR,GAAG;gBACH,UAAU;;;;;;;;;;;;;;;;;;;GAoCrB,CAAC;AAEF,eAAO,MAAM,yCAAyC;;;;;;;;YAS9C,KAAK;YACL,GAAG;;;;;;;gBAQC,MAAM;gBACN,GAAG;gBACH,MAAM;gBACN,QAAQ;gBACR,GAAG;gBACH,UAAU;;;;;;;;;;;;;;;;;;;GAiCrB,CAAC;AAEF,eAAO,MAAM,gCAAgC,EAAE,cAsC9C,CAAC;AAEF,eAAO,MAAM,0BAA0B,EAAE,mBAAmB,EAmC3D,CAAC;AAEF,eAAO,MAAM,iCAAiC,EAAE,cAgC/C,CAAC;AAEF,eAAO,MAAM,sBAAsB;;;;;;;;YAS3B,KAAK;YACL,GAAG;;;;;;;;gBA+BC,GAAG;gBACH,QAAQ;gBACR,GAAG;;;;;;;;;;;;;;;;;;;GAqBd,CAAC"}