@perses-dev/table-plugin 0.11.1 → 0.11.2

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.
@@ -14,10 +14,18 @@
14
14
  Object.defineProperty(exports, "__esModule", {
15
15
  value: true
16
16
  });
17
- Object.defineProperty(exports, "TableExportAction", {
18
- enumerable: true,
19
- get: function() {
17
+ function _export(target, all) {
18
+ for(var name in all)Object.defineProperty(target, name, {
19
+ enumerable: true,
20
+ get: Object.getOwnPropertyDescriptor(all, name).get
21
+ });
22
+ }
23
+ _export(exports, {
24
+ get TableExportAction () {
20
25
  return TableExportAction;
26
+ },
27
+ get buildTableData () {
28
+ return buildTableData;
21
29
  }
22
30
  });
23
31
  const _jsxruntime = require("react/jsx-runtime");
@@ -26,6 +34,8 @@ const _pluginsystem = require("@perses-dev/plugin-system");
26
34
  const _components = require("@perses-dev/components");
27
35
  const _material = require("@mui/material");
28
36
  const _Download = /*#__PURE__*/ _interop_require_default(require("mdi-material-ui/Download"));
37
+ const _core = require("@perses-dev/core");
38
+ const _tabledatautils = require("./table-data-utils");
29
39
  function _interop_require_default(obj) {
30
40
  return obj && obj.__esModule ? obj : {
31
41
  default: obj
@@ -72,39 +82,86 @@ function _interop_require_wildcard(obj, nodeInterop) {
72
82
  }
73
83
  return newObj;
74
84
  }
75
- const TableExportAction = ({ queryResults, definition })=>{
76
- const exportableData = (0, _react.useMemo)(()=>{
77
- return (0, _pluginsystem.extractExportableData)(queryResults);
78
- }, [
79
- queryResults
80
- ]);
81
- const canExport = (0, _react.useMemo)(()=>{
82
- return (0, _pluginsystem.isExportableData)(exportableData);
83
- }, [
84
- exportableData
85
+ function buildTableData(queryResults, spec) {
86
+ // Use shared utility with forExport=true to get raw scalar values
87
+ const rawData = (0, _tabledatautils.buildRawTableData)(queryResults, spec, {
88
+ forExport: true
89
+ });
90
+ const transformed = (0, _core.transformData)(rawData, spec.transforms ?? []);
91
+ const allKeys = [];
92
+ for (const entry of transformed){
93
+ for (const key of Object.keys(entry)){
94
+ if (!allKeys.includes(key)) allKeys.push(key);
95
+ }
96
+ }
97
+ const columnSettings = spec.columnSettings ?? [];
98
+ const columns = [];
99
+ const customized = new Set();
100
+ for (const col of columnSettings){
101
+ if (customized.has(col.name)) continue;
102
+ customized.add(col.name);
103
+ if (col.hide) continue;
104
+ columns.push({
105
+ key: col.name,
106
+ header: col.header ?? col.name
107
+ });
108
+ }
109
+ if (!spec.defaultColumnHidden) {
110
+ for (const key of allKeys){
111
+ if (!customized.has(key)) {
112
+ columns.push({
113
+ key,
114
+ header: key
115
+ });
116
+ }
117
+ }
118
+ }
119
+ return {
120
+ data: transformed,
121
+ columns
122
+ };
123
+ }
124
+ const TableExportAction = ({ queryResults, spec, definition })=>{
125
+ const tableData = (0, _react.useMemo)(()=>buildTableData(queryResults, spec), [
126
+ queryResults,
127
+ spec
85
128
  ]);
129
+ const canExport = tableData.data.length > 0 && tableData.columns.length > 0;
86
130
  const handleExport = (0, _react.useCallback)(()=>{
87
- if (!exportableData || !canExport) return;
131
+ if (!canExport) return;
88
132
  try {
89
- const title = definition?.spec?.display?.name || 'Time Series Data';
90
- const csvBlob = (0, _pluginsystem.exportDataAsCSV)({
91
- data: exportableData
133
+ const title = definition?.spec?.display?.name || 'Table Data';
134
+ const { data, columns } = tableData;
135
+ const headerRow = columns.map((c)=>(0, _pluginsystem.escapeCsvValue)(c.header)).join(',');
136
+ const dataRows = data.map((row)=>columns.map((col)=>(0, _pluginsystem.escapeCsvValue)(row[col.key])).join(','));
137
+ const csvString = [
138
+ headerRow,
139
+ ...dataRows
140
+ ].join('\n') + '\n';
141
+ const csvBlob = new Blob([
142
+ csvString
143
+ ], {
144
+ type: 'text/csv;charset=utf-8'
92
145
  });
93
146
  const baseFilename = (0, _pluginsystem.sanitizeFilename)(title);
94
147
  const filename = `${baseFilename}_data.csv`;
95
- const link = document.createElement('a');
96
- link.href = URL.createObjectURL(csvBlob);
97
- link.download = filename;
98
- document.body.appendChild(link);
99
- link.click();
100
- document.body.removeChild(link);
101
- URL.revokeObjectURL(link.href);
148
+ const url = URL.createObjectURL(csvBlob);
149
+ try {
150
+ const link = document.createElement('a');
151
+ link.href = url;
152
+ link.download = filename;
153
+ document.body.appendChild(link);
154
+ link.click();
155
+ document.body.removeChild(link);
156
+ } finally{
157
+ URL.revokeObjectURL(url);
158
+ }
102
159
  } catch (error) {
103
- console.error('Time series export failed:', error);
160
+ console.error('Table CSV export failed:', error);
104
161
  }
105
162
  }, [
106
- exportableData,
107
163
  canExport,
164
+ tableData,
108
165
  definition
109
166
  ]);
110
167
  if (!canExport) {
@@ -115,7 +172,7 @@ const TableExportAction = ({ queryResults, definition })=>{
115
172
  children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.IconButton, {
116
173
  size: "small",
117
174
  onClick: handleExport,
118
- "aria-label": "Export time series data as CSV",
175
+ "aria-label": "Export table data as CSV",
119
176
  children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_Download.default, {
120
177
  fontSize: "inherit"
121
178
  })
@@ -36,6 +36,7 @@ const _dashboards = require("@perses-dev/dashboards");
36
36
  const _pluginsystem = require("@perses-dev/plugin-system");
37
37
  const _react = require("react");
38
38
  const _models = require("../models");
39
+ const _tabledatautils = require("../table-data-utils");
39
40
  const _EmbeddedPanel = require("./EmbeddedPanel");
40
41
  function generateCellContentConfig(column) {
41
42
  const plugin = column.plugin;
@@ -225,7 +226,7 @@ function ColumnFilterDropdown({ allValues, selectedValues, onFilterChange, theme
225
226
  function getTablePanelQueryOptions(spec) {
226
227
  // if any cell renders a panel plugin, perform a range query instead of an instant query
227
228
  return {
228
- mode: (spec.columnSettings ?? []).some((c)=>c.plugin) ? 'range' : 'instant'
229
+ mode: (0, _tabledatautils.getTablePanelQueryMode)(spec)
229
230
  };
230
231
  }
231
232
  function TablePanel({ contentDimensions, spec, queryResults }) {
@@ -273,53 +274,12 @@ function TablePanel({ contentDimensions, spec, queryResults }) {
273
274
  clearSelection
274
275
  ]);
275
276
  // TODO: handle other query types
276
- const queryMode = getTablePanelQueryOptions(spec).mode;
277
277
  const rawData = (0, _react.useMemo)(()=>{
278
- // Transform query results to a tabular format:
279
- // [ { timestamp: 123, value: 456, labelName1: labelValue1 }, ... ]
280
- return queryResults.flatMap((data, queryIndex)=>data.data.series.map((ts)=>({
281
- data,
282
- ts,
283
- queryIndex
284
- }))).map(({ data, ts, queryIndex })=>{
285
- if (ts.values[0] === undefined) {
286
- return {
287
- ...ts.labels
288
- };
289
- }
290
- // If there are multiple queries, we need to add the query index to the value key and label key to avoid conflicts
291
- const valueColumnName = queryResults.length === 1 ? 'value' : `value #${queryIndex + 1}`;
292
- const labels = queryResults.length === 1 ? ts.labels : Object.entries(ts.labels ?? {}).reduce((acc, [key, value])=>{
293
- if (key) acc[`${key} #${queryIndex + 1}`] = value;
294
- return acc;
295
- }, {});
296
- // If the cell visualization is a panel plugin, filter the data by the current series
297
- const columnValue = (spec.columnSettings ?? []).find((x)=>x.name === valueColumnName)?.plugin ? {
298
- ...data,
299
- data: {
300
- ...data.data,
301
- series: data.data.series.filter((s)=>s === ts)
302
- }
303
- } : ts.values[0][1];
304
- if (queryMode === 'instant') {
305
- // Timestamp is not indexed as it will be the same for all queries
306
- return {
307
- timestamp: ts.values[0][0],
308
- [valueColumnName]: columnValue,
309
- ...labels
310
- };
311
- } else {
312
- // Don't add a timestamp for range queries
313
- return {
314
- [valueColumnName]: columnValue,
315
- ...labels
316
- };
317
- }
318
- });
278
+ // Transform query results to a tabular format using shared utility
279
+ return (0, _tabledatautils.buildRawTableData)(queryResults, spec);
319
280
  }, [
320
281
  queryResults,
321
- queryMode,
322
- spec.columnSettings
282
+ spec
323
283
  ]);
324
284
  // Transform will be applied by their orders on the original data
325
285
  const data = (0, _react.useMemo)(()=>(0, _core.transformData)(rawData, spec.transforms ?? []), [
@@ -0,0 +1,83 @@
1
+ // Copyright 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: Object.getOwnPropertyDescriptor(all, name).get
21
+ });
22
+ }
23
+ _export(exports, {
24
+ get buildRawTableData () {
25
+ return buildRawTableData;
26
+ },
27
+ get getTablePanelQueryMode () {
28
+ return getTablePanelQueryMode;
29
+ }
30
+ });
31
+ function getTablePanelQueryMode(spec) {
32
+ return (spec.columnSettings ?? []).some((c)=>c.plugin) ? 'range' : 'instant';
33
+ }
34
+ function buildRawTableData(queryResults, spec, options = {}) {
35
+ const { forExport = false } = options;
36
+ const queryMode = getTablePanelQueryMode(spec);
37
+ return queryResults.flatMap((data, queryIndex)=>(data.data?.series ?? []).map((ts)=>({
38
+ data,
39
+ ts,
40
+ queryIndex
41
+ }))).map(({ data, ts, queryIndex })=>{
42
+ if (ts.values[0] === undefined) {
43
+ return {
44
+ ...ts.labels
45
+ };
46
+ }
47
+ // If there are multiple queries, add query index to value key and label keys to avoid conflicts
48
+ const valueColumnName = queryResults.length === 1 ? 'value' : `value #${queryIndex + 1}`;
49
+ const labels = queryResults.length === 1 ? ts.labels : Object.entries(ts.labels ?? {}).reduce((acc, [key, value])=>{
50
+ if (key) acc[`${key} #${queryIndex + 1}`] = value;
51
+ return acc;
52
+ }, {});
53
+ // For export: always use raw scalar values
54
+ // For rendering: plugin columns get embedded PanelData objects
55
+ let columnValue;
56
+ if (forExport) {
57
+ columnValue = ts.values[0][1];
58
+ } else {
59
+ const hasPlugin = (spec.columnSettings ?? []).find((x)=>x.name === valueColumnName)?.plugin;
60
+ columnValue = hasPlugin ? {
61
+ ...data,
62
+ data: {
63
+ ...data.data,
64
+ series: data.data.series.filter((s)=>s === ts)
65
+ }
66
+ } : ts.values[0][1];
67
+ }
68
+ if (queryMode === 'instant') {
69
+ // Timestamp is not indexed as it will be the same for all queries
70
+ return {
71
+ timestamp: ts.values[0][0],
72
+ [valueColumnName]: columnValue,
73
+ ...labels
74
+ };
75
+ } else {
76
+ // Don't add a timestamp for range queries
77
+ return {
78
+ [valueColumnName]: columnValue,
79
+ ...labels
80
+ };
81
+ }
82
+ });
83
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"TablePanel.d.ts","sourceRoot":"","sources":["../../../src/components/TablePanel.tsx"],"names":[],"mappings":"AAeA,OAAO,EAAkD,cAAc,EAAiB,MAAM,kBAAkB,CAAC;AAEjH,OAAO,EAGL,UAAU,EAIX,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EAAE,YAAY,EAAqD,MAAM,OAAO,CAAC;AACxF,OAAO,EAAiD,YAAY,EAAE,MAAM,WAAW,CAAC;AA+KxF,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,YAAY,GAAG;IAAE,IAAI,EAAE,SAAS,GAAG,OAAO,CAAA;CAAE,CAK3F;AAED,MAAM,MAAM,UAAU,GAAG,UAAU,CAAC,YAAY,EAAE,cAAc,CAAC,CAAC;AAElE,wBAAgB,UAAU,CAAC,EAAE,iBAAiB,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,UAAU,GAAG,YAAY,GAAG,IAAI,CAybrG"}
1
+ {"version":3,"file":"TablePanel.d.ts","sourceRoot":"","sources":["../../../src/components/TablePanel.tsx"],"names":[],"mappings":"AAeA,OAAO,EAA8B,cAAc,EAAiB,MAAM,kBAAkB,CAAC;AAE7F,OAAO,EAGL,UAAU,EAIX,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EAAE,YAAY,EAAqD,MAAM,OAAO,CAAC;AACxF,OAAO,EAAiD,YAAY,EAAE,MAAM,WAAW,CAAC;AAgLxF,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,YAAY,GAAG;IAAE,IAAI,EAAE,SAAS,GAAG,OAAO,CAAA;CAAE,CAK3F;AAED,MAAM,MAAM,UAAU,GAAG,UAAU,CAAC,YAAY,EAAE,cAAc,CAAC,CAAC;AAElE,wBAAgB,UAAU,CAAC,EAAE,iBAAiB,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,UAAU,GAAG,YAAY,GAAG,IAAI,CAwZrG"}
@@ -18,6 +18,7 @@ import { useSelectionItemActions } from '@perses-dev/dashboards';
18
18
  import { replaceVariablesInString, useAllVariableValues } from '@perses-dev/plugin-system';
19
19
  import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
20
20
  import { evaluateConditionalFormatting } from '../models';
21
+ import { buildRawTableData, getTablePanelQueryMode } from '../table-data-utils';
21
22
  import { EmbeddedPanel } from './EmbeddedPanel';
22
23
  function generateCellContentConfig(column) {
23
24
  const plugin = column.plugin;
@@ -207,7 +208,7 @@ function ColumnFilterDropdown({ allValues, selectedValues, onFilterChange, theme
207
208
  export function getTablePanelQueryOptions(spec) {
208
209
  // if any cell renders a panel plugin, perform a range query instead of an instant query
209
210
  return {
210
- mode: (spec.columnSettings ?? []).some((c)=>c.plugin) ? 'range' : 'instant'
211
+ mode: getTablePanelQueryMode(spec)
211
212
  };
212
213
  }
213
214
  export function TablePanel({ contentDimensions, spec, queryResults }) {
@@ -255,53 +256,12 @@ export function TablePanel({ contentDimensions, spec, queryResults }) {
255
256
  clearSelection
256
257
  ]);
257
258
  // TODO: handle other query types
258
- const queryMode = getTablePanelQueryOptions(spec).mode;
259
259
  const rawData = useMemo(()=>{
260
- // Transform query results to a tabular format:
261
- // [ { timestamp: 123, value: 456, labelName1: labelValue1 }, ... ]
262
- return queryResults.flatMap((data, queryIndex)=>data.data.series.map((ts)=>({
263
- data,
264
- ts,
265
- queryIndex
266
- }))).map(({ data, ts, queryIndex })=>{
267
- if (ts.values[0] === undefined) {
268
- return {
269
- ...ts.labels
270
- };
271
- }
272
- // If there are multiple queries, we need to add the query index to the value key and label key to avoid conflicts
273
- const valueColumnName = queryResults.length === 1 ? 'value' : `value #${queryIndex + 1}`;
274
- const labels = queryResults.length === 1 ? ts.labels : Object.entries(ts.labels ?? {}).reduce((acc, [key, value])=>{
275
- if (key) acc[`${key} #${queryIndex + 1}`] = value;
276
- return acc;
277
- }, {});
278
- // If the cell visualization is a panel plugin, filter the data by the current series
279
- const columnValue = (spec.columnSettings ?? []).find((x)=>x.name === valueColumnName)?.plugin ? {
280
- ...data,
281
- data: {
282
- ...data.data,
283
- series: data.data.series.filter((s)=>s === ts)
284
- }
285
- } : ts.values[0][1];
286
- if (queryMode === 'instant') {
287
- // Timestamp is not indexed as it will be the same for all queries
288
- return {
289
- timestamp: ts.values[0][0],
290
- [valueColumnName]: columnValue,
291
- ...labels
292
- };
293
- } else {
294
- // Don't add a timestamp for range queries
295
- return {
296
- [valueColumnName]: columnValue,
297
- ...labels
298
- };
299
- }
300
- });
260
+ // Transform query results to a tabular format using shared utility
261
+ return buildRawTableData(queryResults, spec);
301
262
  }, [
302
263
  queryResults,
303
- queryMode,
304
- spec.columnSettings
264
+ spec
305
265
  ]);
306
266
  // Transform will be applied by their orders on the original data
307
267
  const data = useMemo(()=>transformData(rawData, spec.transforms ?? []), [
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/TablePanel.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, Theme, Typography, useTheme } from '@mui/material';\nimport { Table, TableCellConfigs, TableColumnConfig, useSelection } from '@perses-dev/components';\nimport { formatValue, Labels, QueryDataType, TimeSeries, TimeSeriesData, transformData } from '@perses-dev/core';\nimport { useSelectionItemActions } from '@perses-dev/dashboards';\nimport {\n ActionOptions,\n PanelData,\n PanelProps,\n replaceVariablesInString,\n useAllVariableValues,\n VariableStateMap,\n} from '@perses-dev/plugin-system';\nimport { ColumnFiltersState, PaginationState, RowSelectionState, SortingState } from '@tanstack/react-table';\nimport { ReactElement, useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { ColumnSettings, evaluateConditionalFormatting, TableOptions } from '../models';\nimport { EmbeddedPanel } from './EmbeddedPanel';\n\nfunction generateCellContentConfig(\n column: ColumnSettings\n): Pick<TableColumnConfig<unknown>, 'cellDescription' | 'cell'> {\n const plugin = column.plugin;\n if (plugin !== undefined) {\n return {\n cell: (ctx): ReactElement => {\n const panelData: PanelData<QueryDataType> | undefined = ctx.getValue();\n if (!panelData) return <></>;\n return <EmbeddedPanel kind={plugin.kind} spec={plugin.spec} queryResults={[panelData]} />;\n },\n cellDescription: column.cellDescription ? (): string => `${column.cellDescription}` : (): string => '', // disable hover text\n };\n }\n\n return {\n cell: (ctx): ReactElement | string => {\n const cellValue = ctx.getValue();\n return typeof cellValue === 'number' && column.format ? formatValue(cellValue, column.format) : cellValue;\n },\n cellDescription: column.cellDescription ? (): string => `${column.cellDescription}` : undefined, // TODO: variable rendering + cell value\n };\n}\n\ninterface ColumnFilterDropdownProps {\n allValues: Array<string | number>;\n selectedValues: Array<string | number>;\n onFilterChange: (values: Array<string | number>) => void;\n theme: Theme;\n}\n\nfunction ColumnFilterDropdown({\n allValues,\n selectedValues,\n onFilterChange,\n theme,\n}: ColumnFilterDropdownProps): ReactElement {\n const values = [...new Set(allValues)].filter((v) => v !== null).sort();\n if (values.length === 0) {\n return (\n <div\n data-filter-dropdown\n style={{\n width: 200,\n padding: 10,\n backgroundColor: theme.palette.background.paper,\n border: `1px solid ${theme.palette.divider}`,\n borderRadius: 4,\n boxShadow: theme.shadows[4],\n }}\n >\n <div style={{ color: theme.palette.text.secondary, fontSize: 14 }}>No values found</div>\n </div>\n );\n }\n\n return (\n <div\n data-filter-dropdown\n style={{\n width: 200,\n padding: 10,\n backgroundColor: theme.palette.background.paper,\n border: `1px solid ${theme.palette.divider}`,\n borderRadius: 4,\n boxShadow: theme.shadows[4],\n maxHeight: 250,\n overflowY: 'auto',\n }}\n >\n <div style={{ marginBottom: 8, fontSize: 14, fontWeight: 'bold' }}>\n <label style={{ display: 'flex', alignItems: 'center', cursor: 'pointer' }}>\n <input\n type=\"checkbox\"\n checked={selectedValues.length === values.length && values.length > 0}\n onChange={(e) => onFilterChange(e.target.checked ? values : [])}\n style={{ marginRight: 8 }}\n />\n <span style={{ color: theme.palette.text.primary }}>Select All ({values.length})</span>\n </label>\n </div>\n <hr\n style={{\n margin: '8px 0',\n border: 'none',\n borderTop: `1px solid ${theme.palette.divider}`,\n }}\n />\n {values.map((value, index) => (\n <div key={`value-${index}`} style={{ marginBottom: 4 }}>\n <label\n style={{\n display: 'flex',\n alignItems: 'center',\n cursor: 'pointer',\n padding: '2px 0',\n borderRadius: 2,\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.backgroundColor = theme.palette.action.hover;\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.backgroundColor = 'transparent';\n }}\n >\n <input\n type=\"checkbox\"\n checked={selectedValues.includes(value)}\n onChange={(e) => {\n if (e.target.checked) {\n onFilterChange([...selectedValues, value]);\n } else {\n onFilterChange(selectedValues.filter((v) => v !== value));\n }\n }}\n style={{ marginRight: 8 }}\n />\n <span\n style={{\n fontSize: 14,\n color: theme.palette.text.primary,\n }}\n >\n {value === null || value === undefined || value === '' ? '(empty)' : String(value)}\n </span>\n </label>\n </div>\n ))}\n </div>\n );\n}\n\n/*\n * Generate column config from column definitions, if a column has multiple definitions, the first one will be used.\n * If column is hidden, return undefined.\n * If column do not have a definition, return a default column config.\n */\nfunction generateColumnConfig(\n name: string,\n columnSettings: ColumnSettings[],\n allVariables: VariableStateMap\n): TableColumnConfig<unknown> | undefined {\n for (const column of columnSettings) {\n if (column.name === name) {\n if (column.hide) {\n return undefined;\n }\n\n const { name, header, headerDescription, enableSorting, width, align, dataLink } = column;\n const modifiedDataLink = dataLink\n ? { ...dataLink, url: replaceVariablesInString(dataLink.url, allVariables) }\n : undefined;\n\n return {\n accessorKey: name,\n header: header ?? name,\n headerDescription,\n enableSorting,\n width,\n align,\n dataLink: modifiedDataLink,\n ...generateCellContentConfig(column),\n };\n }\n }\n\n return {\n accessorKey: name,\n header: name,\n };\n}\n\nexport function getTablePanelQueryOptions(spec: TableOptions): { mode: 'instant' | 'range' } {\n // if any cell renders a panel plugin, perform a range query instead of an instant query\n return {\n mode: (spec.columnSettings ?? []).some((c) => c.plugin) ? 'range' : 'instant',\n };\n}\n\nexport type TableProps = PanelProps<TableOptions, TimeSeriesData>;\n\nexport function TablePanel({ contentDimensions, spec, queryResults }: TableProps): ReactElement | null {\n const theme = useTheme();\n const allVariables = useAllVariableValues();\n\n const selectionEnabled = spec.selection?.enabled ?? false;\n const { selectionMap, setSelection, clearSelection } = useSelection<Record<string, unknown>, string>();\n\n const itemActionsConfig = spec.actions ? (spec.actions as ActionOptions) : undefined;\n const itemActionsListConfig =\n itemActionsConfig?.enabled && itemActionsConfig.displayWithItem ? itemActionsConfig.actionsList : [];\n\n const { getItemActionButtons, confirmDialog, actionButtons } = useSelectionItemActions({\n actions: itemActionsListConfig,\n variableState: allVariables,\n });\n\n const filteredDataRef = useRef<Array<Record<string, unknown>>>([]);\n\n // Convert selectionMap to TanStack's RowSelectionState format\n const rowSelection = useMemo((): RowSelectionState => {\n const result: RowSelectionState = {};\n selectionMap.forEach((_, id) => {\n result[id] = true;\n });\n return result;\n }, [selectionMap]);\n\n const handleRowSelectionChange = useCallback(\n (newRowSelection: RowSelectionState) => {\n const newSelection: Array<{ id: string; item: Record<string, unknown> }> = [];\n for (const [id, isSelected] of Object.entries(newRowSelection)) {\n if (isSelected) {\n const index = parseInt(id, 10);\n if (filteredDataRef.current[index] !== undefined) {\n newSelection.push({ id, item: filteredDataRef.current[index] });\n }\n }\n }\n\n if (newSelection.length === 0) {\n clearSelection();\n } else {\n setSelection(newSelection);\n }\n },\n [setSelection, clearSelection]\n );\n\n // TODO: handle other query types\n const queryMode = getTablePanelQueryOptions(spec).mode;\n const rawData: Array<Record<string, unknown>> = useMemo(() => {\n // Transform query results to a tabular format:\n // [ { timestamp: 123, value: 456, labelName1: labelValue1 }, ... ]\n return queryResults\n .flatMap((data: PanelData<TimeSeriesData>, queryIndex: number) =>\n data.data.series.map((ts: TimeSeries) => ({ data, ts, queryIndex }))\n )\n .map(({ data, ts, queryIndex }: { data: PanelData<TimeSeriesData>; ts: TimeSeries; queryIndex: number }) => {\n if (ts.values[0] === undefined) {\n return { ...ts.labels };\n }\n\n // If there are multiple queries, we need to add the query index to the value key and label key to avoid conflicts\n const valueColumnName = queryResults.length === 1 ? 'value' : `value #${queryIndex + 1}`;\n const labels =\n queryResults.length === 1\n ? ts.labels\n : Object.entries(ts.labels ?? {}).reduce((acc, [key, value]) => {\n if (key) acc[`${key} #${queryIndex + 1}`] = value;\n return acc;\n }, {} as Labels);\n\n // If the cell visualization is a panel plugin, filter the data by the current series\n const columnValue = (spec.columnSettings ?? []).find((x) => x.name === valueColumnName)?.plugin\n ? { ...data, data: { ...data.data, series: data.data.series.filter((s) => s === ts) } }\n : ts.values[0][1];\n\n if (queryMode === 'instant') {\n // Timestamp is not indexed as it will be the same for all queries\n return { timestamp: ts.values[0][0], [valueColumnName]: columnValue, ...labels };\n } else {\n // Don't add a timestamp for range queries\n return { [valueColumnName]: columnValue, ...labels };\n }\n });\n }, [queryResults, queryMode, spec.columnSettings]);\n\n // Transform will be applied by their orders on the original data\n const data = useMemo(() => transformData(rawData, spec.transforms ?? []), [rawData, spec.transforms]);\n\n const keys: string[] = useMemo(() => {\n const result: string[] = [];\n\n for (const entry of data) {\n for (const key of Object.keys(entry)) {\n if (!result.includes(key)) {\n result.push(key);\n }\n }\n }\n\n return result;\n }, [data]);\n\n // fetch unique values for each column of filtering\n const columnUniqueValues = useMemo(() => {\n const uniqueValues: Record<string, Array<string | number>> = {};\n\n keys.forEach((key) => {\n const values = data.map((row) => row[key]).filter((val) => val !== null && val !== undefined && val !== '');\n uniqueValues[key] = Array.from(new Set(values as Array<string | number>));\n });\n\n return uniqueValues;\n }, [data, keys]);\n\n // Generate columns and map each column accessor to its settings index and data key\n const columns: Array<TableColumnConfig<unknown>> = useMemo(() => {\n const columns: Array<TableColumnConfig<unknown>> = [];\n const customizedColumns = new Set<string>();\n\n // Process columnSettings if they exist\n for (const columnSetting of spec.columnSettings ?? []) {\n if (customizedColumns.has(columnSetting.name)) continue; // Skip duplicates\n\n const columnConfig = generateColumnConfig(columnSetting.name, spec.columnSettings ?? [], allVariables);\n if (columnConfig !== undefined) {\n columns.push(columnConfig);\n customizedColumns.add(columnSetting.name);\n }\n }\n\n // Add remaining columns if defaultColumnHidden is false\n if (!spec.defaultColumnHidden) {\n for (const key of keys) {\n if (!customizedColumns.has(key)) {\n const columnConfig = generateColumnConfig(key, spec.columnSettings ?? [], allVariables);\n if (columnConfig !== undefined) {\n columns.push(columnConfig);\n }\n }\n }\n }\n\n return columns;\n }, [keys, spec.columnSettings, spec.defaultColumnHidden, allVariables]);\n\n // Generate cell settings that will be used by the table to render cells (text color, background color, ...)\n const cellConfigs: TableCellConfigs = useMemo(() => {\n // If there are no cell settings globally or per column, return an empty object\n if (spec.cellSettings === undefined && !spec.columnSettings?.some((col) => col.cellSettings !== undefined)) {\n return {};\n }\n\n const result: TableCellConfigs = {};\n\n let index = 0;\n for (const row of data) {\n // Transforming key to object to extend the row with undefined values if the key is not present\n // for checking the cell config \"Misc\" condition with \"null\"\n const keysAsObj = keys.reduce(\n (acc, key) => {\n acc[key] = undefined;\n return acc;\n },\n {} as Record<string, undefined>\n );\n\n const extendRow = {\n ...keysAsObj,\n ...row,\n };\n\n // Generate cellConfigs for each column (including duplicates with different headers)\n for (const [key, value] of Object.entries(extendRow)) {\n // First, try to get cell config from global cell settings\n let cellConfig = evaluateConditionalFormatting(value, spec.cellSettings ?? []);\n\n // Then, try to get cell config from column-specific cell settings\n const columnSetting = spec.columnSettings?.find((col) => col.name === key);\n if (columnSetting?.cellSettings?.length) {\n const columnCellConfig = evaluateConditionalFormatting(value, columnSetting.cellSettings);\n // Column-specific settings take precedence over global settings\n if (columnCellConfig) {\n cellConfig = columnCellConfig;\n }\n }\n\n if (cellConfig) {\n result[`${index}_${key}`] = cellConfig;\n }\n }\n index++;\n }\n\n return result;\n }, [data, keys, spec.cellSettings, spec.columnSettings]);\n\n function generateDefaultSortingState(): SortingState {\n return (\n spec.columnSettings\n ?.filter((column) => column.sort !== undefined)\n .map((column) => {\n return {\n id: column.name,\n desc: column.sort === 'desc',\n };\n }) ?? []\n );\n }\n\n const [sorting, setSorting] = useState<SortingState>(generateDefaultSortingState());\n\n // Filtering state\n const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([]);\n const [filterAnchorEl, setFilterAnchorEl] = useState<{ [key: string]: HTMLElement | null }>({});\n const [openFilterColumn, setOpenFilterColumn] = useState<string | null>(null);\n\n // get selected values for a column\n const getSelectedFilterValues = (columnId: string): Array<string | number> => {\n const filter = columnFilters.find((f) => f.id === columnId);\n return filter ? (filter.value as Array<string | number>) : [];\n };\n\n // update column filter\n const updateColumnFilter = (columnId: string, values: Array<string | number>): void => {\n const newFilters = columnFilters.filter((f) => f.id !== columnId);\n if (values.length > 0) {\n newFilters.push({ id: columnId, value: values });\n }\n setColumnFilters(newFilters);\n };\n\n // Handle filter clicks\n const handleFilterClick = (event: React.MouseEvent<HTMLButtonElement>, columnId: string): void => {\n event.preventDefault();\n event.stopPropagation();\n setFilterAnchorEl({ ...filterAnchorEl, [columnId]: event.currentTarget });\n setOpenFilterColumn(columnId);\n };\n\n const handleFilterClose = (): void => {\n setFilterAnchorEl({});\n setOpenFilterColumn(null);\n };\n\n // Close filter when clicking outside\n useEffect(() => {\n if (!openFilterColumn) return;\n\n const handleClick = (e: MouseEvent): void => {\n const target = e.target as Element;\n if (!target.closest('[data-filter-dropdown]') && !target.closest('button')) {\n handleFilterClose();\n }\n };\n\n const timer = setTimeout(() => {\n document.addEventListener('click', handleClick);\n }, 100);\n\n return (): void => {\n clearTimeout(timer);\n document.removeEventListener('click', handleClick);\n };\n }, [openFilterColumn]);\n\n // filter data based on the current filters\n const filteredData = useMemo(() => {\n let filtered = [...data];\n\n // apply column filters if enabled\n if (spec.enableFiltering && columnFilters.length > 0) {\n filtered = filtered.filter((row) => {\n return columnFilters.every((filter) => {\n const value = row[filter.id];\n const filterValues = filter.value as Array<string | number>;\n\n if (!filterValues || filterValues.length === 0) return true; // No filter values means no filtering\n\n // Check if the row value is in the selected filter values\n return filterValues.includes(value as string | number);\n });\n });\n }\n\n return filtered;\n }, [data, columnFilters, spec.enableFiltering]);\n\n // Keep ref in sync with filtered data for use in selection handler\n filteredDataRef.current = filteredData;\n\n const [pagination, setPagination] = useState<PaginationState | undefined>(\n spec.pagination ? { pageIndex: 0, pageSize: 10 } : undefined\n );\n\n useEffect(() => {\n // If the pagination setting changes from no pagination to pagination, but the pagination state is undefined, update the pagination state\n if (spec.pagination && !pagination) {\n setPagination({ pageIndex: 0, pageSize: 10 });\n } else if (!spec.pagination && pagination) {\n setPagination(undefined);\n }\n }, [spec.pagination, pagination]);\n\n if (contentDimensions === undefined) {\n return null;\n }\n\n if (!data?.length) {\n return (\n <Box\n sx={{\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n height: '100%',\n }}\n >\n <Typography>No data</Typography>\n </Box>\n );\n }\n\n return (\n <>\n {confirmDialog}\n {spec.enableFiltering && (\n <div\n style={{\n display: 'flex',\n background: theme.palette.background.default,\n borderBottom: `1px solid ${theme.palette.divider}`,\n width: contentDimensions.width,\n boxSizing: 'border-box',\n }}\n >\n {columns.map((column, idx) => {\n const filters = getSelectedFilterValues(column.accessorKey as string);\n const columnWidth = column.width || spec.defaultColumnWidth;\n return (\n <div\n key={`filter-${idx}`}\n style={{\n padding: '8px',\n borderRight: idx < columns.length - 1 ? `1px solid ${theme.palette.divider}` : 'none',\n width: columnWidth,\n minWidth: columnWidth,\n maxWidth: columnWidth,\n display: 'flex',\n alignItems: 'center',\n position: 'relative',\n boxSizing: 'border-box',\n flex: typeof columnWidth === 'number' ? 'none' : '1 1 auto',\n }}\n >\n <span\n style={{\n marginRight: 8,\n fontSize: '12px',\n color: theme.palette.text.secondary,\n flex: 1,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n }}\n >\n {filters.length ? `${filters.length} items` : 'All'}\n </span>\n <button\n onClick={(e) => {\n handleFilterClick(e, column.accessorKey as string);\n }}\n style={{\n border: `1px solid ${theme.palette.divider}`,\n background: theme.palette.background.paper,\n cursor: 'pointer',\n fontSize: '12px',\n color: filters.length ? theme.palette.primary.main : theme.palette.text.secondary,\n padding: '4px 8px',\n borderRadius: '4px',\n minWidth: '20px',\n height: '24px',\n flexShrink: 0,\n transition: 'all 0.2s ease',\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.background = theme.palette.action.hover;\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.background = theme.palette.background.paper;\n }}\n type=\"button\"\n >\n ▼\n </button>\n\n {openFilterColumn === column.accessorKey && (\n <div\n style={{\n position: 'absolute',\n top: '100%',\n left: 0,\n zIndex: 1000,\n marginTop: 4,\n }}\n >\n <ColumnFilterDropdown\n allValues={columnUniqueValues[column.accessorKey as string] || []}\n selectedValues={filters}\n onFilterChange={(values) => updateColumnFilter(column.accessorKey as string, values)}\n theme={theme}\n />\n </div>\n )}\n </div>\n );\n })}\n </div>\n )}\n <Table\n data={filteredData}\n columns={columns}\n cellConfigs={cellConfigs}\n height={spec.enableFiltering ? contentDimensions.height - 40 : contentDimensions.height}\n width={contentDimensions.width}\n density={spec.density}\n defaultColumnWidth={spec.defaultColumnWidth}\n defaultColumnHeight={spec.defaultColumnHeight}\n sorting={sorting}\n onSortingChange={setSorting}\n pagination={pagination}\n onPaginationChange={setPagination}\n checkboxSelection={selectionEnabled}\n rowSelection={rowSelection}\n onRowSelectionChange={handleRowSelectionChange}\n getItemActions={({ id, data }) => getItemActionButtons({ id, data: data as Record<string, unknown> })}\n hasItemActions={actionButtons && actionButtons.length > 0}\n />\n </>\n );\n}\n"],"names":["Box","Typography","useTheme","Table","useSelection","formatValue","transformData","useSelectionItemActions","replaceVariablesInString","useAllVariableValues","useCallback","useEffect","useMemo","useRef","useState","evaluateConditionalFormatting","EmbeddedPanel","generateCellContentConfig","column","plugin","undefined","cell","ctx","panelData","getValue","kind","spec","queryResults","cellDescription","cellValue","format","ColumnFilterDropdown","allValues","selectedValues","onFilterChange","theme","values","Set","filter","v","sort","length","div","data-filter-dropdown","style","width","padding","backgroundColor","palette","background","paper","border","divider","borderRadius","boxShadow","shadows","color","text","secondary","fontSize","maxHeight","overflowY","marginBottom","fontWeight","label","display","alignItems","cursor","input","type","checked","onChange","e","target","marginRight","span","primary","hr","margin","borderTop","map","value","index","onMouseEnter","currentTarget","action","hover","onMouseLeave","includes","String","generateColumnConfig","name","columnSettings","allVariables","hide","header","headerDescription","enableSorting","align","dataLink","modifiedDataLink","url","accessorKey","getTablePanelQueryOptions","mode","some","c","TablePanel","contentDimensions","selectionEnabled","selection","enabled","selectionMap","setSelection","clearSelection","itemActionsConfig","actions","itemActionsListConfig","displayWithItem","actionsList","getItemActionButtons","confirmDialog","actionButtons","variableState","filteredDataRef","rowSelection","result","forEach","_","id","handleRowSelectionChange","newRowSelection","newSelection","isSelected","Object","entries","parseInt","current","push","item","queryMode","rawData","flatMap","data","queryIndex","series","ts","labels","valueColumnName","reduce","acc","key","columnValue","find","x","s","timestamp","transforms","keys","entry","columnUniqueValues","uniqueValues","row","val","Array","from","columns","customizedColumns","columnSetting","has","columnConfig","add","defaultColumnHidden","cellConfigs","cellSettings","col","keysAsObj","extendRow","cellConfig","columnCellConfig","generateDefaultSortingState","desc","sorting","setSorting","columnFilters","setColumnFilters","filterAnchorEl","setFilterAnchorEl","openFilterColumn","setOpenFilterColumn","getSelectedFilterValues","columnId","f","updateColumnFilter","newFilters","handleFilterClick","event","preventDefault","stopPropagation","handleFilterClose","handleClick","closest","timer","setTimeout","document","addEventListener","clearTimeout","removeEventListener","filteredData","filtered","enableFiltering","every","filterValues","pagination","setPagination","pageIndex","pageSize","sx","justifyContent","height","default","borderBottom","boxSizing","idx","filters","columnWidth","defaultColumnWidth","borderRight","minWidth","maxWidth","position","flex","overflow","textOverflow","whiteSpace","button","onClick","main","flexShrink","transition","top","left","zIndex","marginTop","density","defaultColumnHeight","onSortingChange","onPaginationChange","checkboxSelection","onRowSelectionChange","getItemActions","hasItemActions"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/components/TablePanel.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, Theme, Typography, useTheme } from '@mui/material';\nimport { Table, TableCellConfigs, TableColumnConfig, useSelection } from '@perses-dev/components';\nimport { formatValue, QueryDataType, TimeSeriesData, transformData } from '@perses-dev/core';\nimport { useSelectionItemActions } from '@perses-dev/dashboards';\nimport {\n ActionOptions,\n PanelData,\n PanelProps,\n replaceVariablesInString,\n useAllVariableValues,\n VariableStateMap,\n} from '@perses-dev/plugin-system';\nimport { ColumnFiltersState, PaginationState, RowSelectionState, SortingState } from '@tanstack/react-table';\nimport { ReactElement, useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { ColumnSettings, evaluateConditionalFormatting, TableOptions } from '../models';\nimport { buildRawTableData, getTablePanelQueryMode } from '../table-data-utils';\nimport { EmbeddedPanel } from './EmbeddedPanel';\n\nfunction generateCellContentConfig(\n column: ColumnSettings\n): Pick<TableColumnConfig<unknown>, 'cellDescription' | 'cell'> {\n const plugin = column.plugin;\n if (plugin !== undefined) {\n return {\n cell: (ctx): ReactElement => {\n const panelData: PanelData<QueryDataType> | undefined = ctx.getValue();\n if (!panelData) return <></>;\n return <EmbeddedPanel kind={plugin.kind} spec={plugin.spec} queryResults={[panelData]} />;\n },\n cellDescription: column.cellDescription ? (): string => `${column.cellDescription}` : (): string => '', // disable hover text\n };\n }\n\n return {\n cell: (ctx): ReactElement | string => {\n const cellValue = ctx.getValue();\n return typeof cellValue === 'number' && column.format ? formatValue(cellValue, column.format) : cellValue;\n },\n cellDescription: column.cellDescription ? (): string => `${column.cellDescription}` : undefined, // TODO: variable rendering + cell value\n };\n}\n\ninterface ColumnFilterDropdownProps {\n allValues: Array<string | number>;\n selectedValues: Array<string | number>;\n onFilterChange: (values: Array<string | number>) => void;\n theme: Theme;\n}\n\nfunction ColumnFilterDropdown({\n allValues,\n selectedValues,\n onFilterChange,\n theme,\n}: ColumnFilterDropdownProps): ReactElement {\n const values = [...new Set(allValues)].filter((v) => v !== null).sort();\n if (values.length === 0) {\n return (\n <div\n data-filter-dropdown\n style={{\n width: 200,\n padding: 10,\n backgroundColor: theme.palette.background.paper,\n border: `1px solid ${theme.palette.divider}`,\n borderRadius: 4,\n boxShadow: theme.shadows[4],\n }}\n >\n <div style={{ color: theme.palette.text.secondary, fontSize: 14 }}>No values found</div>\n </div>\n );\n }\n\n return (\n <div\n data-filter-dropdown\n style={{\n width: 200,\n padding: 10,\n backgroundColor: theme.palette.background.paper,\n border: `1px solid ${theme.palette.divider}`,\n borderRadius: 4,\n boxShadow: theme.shadows[4],\n maxHeight: 250,\n overflowY: 'auto',\n }}\n >\n <div style={{ marginBottom: 8, fontSize: 14, fontWeight: 'bold' }}>\n <label style={{ display: 'flex', alignItems: 'center', cursor: 'pointer' }}>\n <input\n type=\"checkbox\"\n checked={selectedValues.length === values.length && values.length > 0}\n onChange={(e) => onFilterChange(e.target.checked ? values : [])}\n style={{ marginRight: 8 }}\n />\n <span style={{ color: theme.palette.text.primary }}>Select All ({values.length})</span>\n </label>\n </div>\n <hr\n style={{\n margin: '8px 0',\n border: 'none',\n borderTop: `1px solid ${theme.palette.divider}`,\n }}\n />\n {values.map((value, index) => (\n <div key={`value-${index}`} style={{ marginBottom: 4 }}>\n <label\n style={{\n display: 'flex',\n alignItems: 'center',\n cursor: 'pointer',\n padding: '2px 0',\n borderRadius: 2,\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.backgroundColor = theme.palette.action.hover;\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.backgroundColor = 'transparent';\n }}\n >\n <input\n type=\"checkbox\"\n checked={selectedValues.includes(value)}\n onChange={(e) => {\n if (e.target.checked) {\n onFilterChange([...selectedValues, value]);\n } else {\n onFilterChange(selectedValues.filter((v) => v !== value));\n }\n }}\n style={{ marginRight: 8 }}\n />\n <span\n style={{\n fontSize: 14,\n color: theme.palette.text.primary,\n }}\n >\n {value === null || value === undefined || value === '' ? '(empty)' : String(value)}\n </span>\n </label>\n </div>\n ))}\n </div>\n );\n}\n\n/*\n * Generate column config from column definitions, if a column has multiple definitions, the first one will be used.\n * If column is hidden, return undefined.\n * If column do not have a definition, return a default column config.\n */\nfunction generateColumnConfig(\n name: string,\n columnSettings: ColumnSettings[],\n allVariables: VariableStateMap\n): TableColumnConfig<unknown> | undefined {\n for (const column of columnSettings) {\n if (column.name === name) {\n if (column.hide) {\n return undefined;\n }\n\n const { name, header, headerDescription, enableSorting, width, align, dataLink } = column;\n const modifiedDataLink = dataLink\n ? { ...dataLink, url: replaceVariablesInString(dataLink.url, allVariables) }\n : undefined;\n\n return {\n accessorKey: name,\n header: header ?? name,\n headerDescription,\n enableSorting,\n width,\n align,\n dataLink: modifiedDataLink,\n ...generateCellContentConfig(column),\n };\n }\n }\n\n return {\n accessorKey: name,\n header: name,\n };\n}\n\nexport function getTablePanelQueryOptions(spec: TableOptions): { mode: 'instant' | 'range' } {\n // if any cell renders a panel plugin, perform a range query instead of an instant query\n return {\n mode: getTablePanelQueryMode(spec),\n };\n}\n\nexport type TableProps = PanelProps<TableOptions, TimeSeriesData>;\n\nexport function TablePanel({ contentDimensions, spec, queryResults }: TableProps): ReactElement | null {\n const theme = useTheme();\n const allVariables = useAllVariableValues();\n\n const selectionEnabled = spec.selection?.enabled ?? false;\n const { selectionMap, setSelection, clearSelection } = useSelection<Record<string, unknown>, string>();\n\n const itemActionsConfig = spec.actions ? (spec.actions as ActionOptions) : undefined;\n const itemActionsListConfig =\n itemActionsConfig?.enabled && itemActionsConfig.displayWithItem ? itemActionsConfig.actionsList : [];\n\n const { getItemActionButtons, confirmDialog, actionButtons } = useSelectionItemActions({\n actions: itemActionsListConfig,\n variableState: allVariables,\n });\n\n const filteredDataRef = useRef<Array<Record<string, unknown>>>([]);\n\n // Convert selectionMap to TanStack's RowSelectionState format\n const rowSelection = useMemo((): RowSelectionState => {\n const result: RowSelectionState = {};\n selectionMap.forEach((_, id) => {\n result[id] = true;\n });\n return result;\n }, [selectionMap]);\n\n const handleRowSelectionChange = useCallback(\n (newRowSelection: RowSelectionState) => {\n const newSelection: Array<{ id: string; item: Record<string, unknown> }> = [];\n for (const [id, isSelected] of Object.entries(newRowSelection)) {\n if (isSelected) {\n const index = parseInt(id, 10);\n if (filteredDataRef.current[index] !== undefined) {\n newSelection.push({ id, item: filteredDataRef.current[index] });\n }\n }\n }\n\n if (newSelection.length === 0) {\n clearSelection();\n } else {\n setSelection(newSelection);\n }\n },\n [setSelection, clearSelection]\n );\n\n // TODO: handle other query types\n const rawData: Array<Record<string, unknown>> = useMemo(() => {\n // Transform query results to a tabular format using shared utility\n return buildRawTableData(queryResults, spec);\n }, [queryResults, spec]);\n\n // Transform will be applied by their orders on the original data\n const data = useMemo(() => transformData(rawData, spec.transforms ?? []), [rawData, spec.transforms]);\n\n const keys: string[] = useMemo(() => {\n const result: string[] = [];\n\n for (const entry of data) {\n for (const key of Object.keys(entry)) {\n if (!result.includes(key)) {\n result.push(key);\n }\n }\n }\n\n return result;\n }, [data]);\n\n // fetch unique values for each column of filtering\n const columnUniqueValues = useMemo(() => {\n const uniqueValues: Record<string, Array<string | number>> = {};\n\n keys.forEach((key) => {\n const values = data.map((row) => row[key]).filter((val) => val !== null && val !== undefined && val !== '');\n uniqueValues[key] = Array.from(new Set(values as Array<string | number>));\n });\n\n return uniqueValues;\n }, [data, keys]);\n\n // Generate columns and map each column accessor to its settings index and data key\n const columns: Array<TableColumnConfig<unknown>> = useMemo(() => {\n const columns: Array<TableColumnConfig<unknown>> = [];\n const customizedColumns = new Set<string>();\n\n // Process columnSettings if they exist\n for (const columnSetting of spec.columnSettings ?? []) {\n if (customizedColumns.has(columnSetting.name)) continue; // Skip duplicates\n\n const columnConfig = generateColumnConfig(columnSetting.name, spec.columnSettings ?? [], allVariables);\n if (columnConfig !== undefined) {\n columns.push(columnConfig);\n customizedColumns.add(columnSetting.name);\n }\n }\n\n // Add remaining columns if defaultColumnHidden is false\n if (!spec.defaultColumnHidden) {\n for (const key of keys) {\n if (!customizedColumns.has(key)) {\n const columnConfig = generateColumnConfig(key, spec.columnSettings ?? [], allVariables);\n if (columnConfig !== undefined) {\n columns.push(columnConfig);\n }\n }\n }\n }\n\n return columns;\n }, [keys, spec.columnSettings, spec.defaultColumnHidden, allVariables]);\n\n // Generate cell settings that will be used by the table to render cells (text color, background color, ...)\n const cellConfigs: TableCellConfigs = useMemo(() => {\n // If there are no cell settings globally or per column, return an empty object\n if (spec.cellSettings === undefined && !spec.columnSettings?.some((col) => col.cellSettings !== undefined)) {\n return {};\n }\n\n const result: TableCellConfigs = {};\n\n let index = 0;\n for (const row of data) {\n // Transforming key to object to extend the row with undefined values if the key is not present\n // for checking the cell config \"Misc\" condition with \"null\"\n const keysAsObj = keys.reduce(\n (acc, key) => {\n acc[key] = undefined;\n return acc;\n },\n {} as Record<string, undefined>\n );\n\n const extendRow = {\n ...keysAsObj,\n ...row,\n };\n\n // Generate cellConfigs for each column (including duplicates with different headers)\n for (const [key, value] of Object.entries(extendRow)) {\n // First, try to get cell config from global cell settings\n let cellConfig = evaluateConditionalFormatting(value, spec.cellSettings ?? []);\n\n // Then, try to get cell config from column-specific cell settings\n const columnSetting = spec.columnSettings?.find((col) => col.name === key);\n if (columnSetting?.cellSettings?.length) {\n const columnCellConfig = evaluateConditionalFormatting(value, columnSetting.cellSettings);\n // Column-specific settings take precedence over global settings\n if (columnCellConfig) {\n cellConfig = columnCellConfig;\n }\n }\n\n if (cellConfig) {\n result[`${index}_${key}`] = cellConfig;\n }\n }\n index++;\n }\n\n return result;\n }, [data, keys, spec.cellSettings, spec.columnSettings]);\n\n function generateDefaultSortingState(): SortingState {\n return (\n spec.columnSettings\n ?.filter((column) => column.sort !== undefined)\n .map((column) => {\n return {\n id: column.name,\n desc: column.sort === 'desc',\n };\n }) ?? []\n );\n }\n\n const [sorting, setSorting] = useState<SortingState>(generateDefaultSortingState());\n\n // Filtering state\n const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([]);\n const [filterAnchorEl, setFilterAnchorEl] = useState<{ [key: string]: HTMLElement | null }>({});\n const [openFilterColumn, setOpenFilterColumn] = useState<string | null>(null);\n\n // get selected values for a column\n const getSelectedFilterValues = (columnId: string): Array<string | number> => {\n const filter = columnFilters.find((f) => f.id === columnId);\n return filter ? (filter.value as Array<string | number>) : [];\n };\n\n // update column filter\n const updateColumnFilter = (columnId: string, values: Array<string | number>): void => {\n const newFilters = columnFilters.filter((f) => f.id !== columnId);\n if (values.length > 0) {\n newFilters.push({ id: columnId, value: values });\n }\n setColumnFilters(newFilters);\n };\n\n // Handle filter clicks\n const handleFilterClick = (event: React.MouseEvent<HTMLButtonElement>, columnId: string): void => {\n event.preventDefault();\n event.stopPropagation();\n setFilterAnchorEl({ ...filterAnchorEl, [columnId]: event.currentTarget });\n setOpenFilterColumn(columnId);\n };\n\n const handleFilterClose = (): void => {\n setFilterAnchorEl({});\n setOpenFilterColumn(null);\n };\n\n // Close filter when clicking outside\n useEffect(() => {\n if (!openFilterColumn) return;\n\n const handleClick = (e: MouseEvent): void => {\n const target = e.target as Element;\n if (!target.closest('[data-filter-dropdown]') && !target.closest('button')) {\n handleFilterClose();\n }\n };\n\n const timer = setTimeout(() => {\n document.addEventListener('click', handleClick);\n }, 100);\n\n return (): void => {\n clearTimeout(timer);\n document.removeEventListener('click', handleClick);\n };\n }, [openFilterColumn]);\n\n // filter data based on the current filters\n const filteredData = useMemo(() => {\n let filtered = [...data];\n\n // apply column filters if enabled\n if (spec.enableFiltering && columnFilters.length > 0) {\n filtered = filtered.filter((row) => {\n return columnFilters.every((filter) => {\n const value = row[filter.id];\n const filterValues = filter.value as Array<string | number>;\n\n if (!filterValues || filterValues.length === 0) return true; // No filter values means no filtering\n\n // Check if the row value is in the selected filter values\n return filterValues.includes(value as string | number);\n });\n });\n }\n\n return filtered;\n }, [data, columnFilters, spec.enableFiltering]);\n\n // Keep ref in sync with filtered data for use in selection handler\n filteredDataRef.current = filteredData;\n\n const [pagination, setPagination] = useState<PaginationState | undefined>(\n spec.pagination ? { pageIndex: 0, pageSize: 10 } : undefined\n );\n\n useEffect(() => {\n // If the pagination setting changes from no pagination to pagination, but the pagination state is undefined, update the pagination state\n if (spec.pagination && !pagination) {\n setPagination({ pageIndex: 0, pageSize: 10 });\n } else if (!spec.pagination && pagination) {\n setPagination(undefined);\n }\n }, [spec.pagination, pagination]);\n\n if (contentDimensions === undefined) {\n return null;\n }\n\n if (!data?.length) {\n return (\n <Box\n sx={{\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n height: '100%',\n }}\n >\n <Typography>No data</Typography>\n </Box>\n );\n }\n\n return (\n <>\n {confirmDialog}\n {spec.enableFiltering && (\n <div\n style={{\n display: 'flex',\n background: theme.palette.background.default,\n borderBottom: `1px solid ${theme.palette.divider}`,\n width: contentDimensions.width,\n boxSizing: 'border-box',\n }}\n >\n {columns.map((column, idx) => {\n const filters = getSelectedFilterValues(column.accessorKey as string);\n const columnWidth = column.width || spec.defaultColumnWidth;\n return (\n <div\n key={`filter-${idx}`}\n style={{\n padding: '8px',\n borderRight: idx < columns.length - 1 ? `1px solid ${theme.palette.divider}` : 'none',\n width: columnWidth,\n minWidth: columnWidth,\n maxWidth: columnWidth,\n display: 'flex',\n alignItems: 'center',\n position: 'relative',\n boxSizing: 'border-box',\n flex: typeof columnWidth === 'number' ? 'none' : '1 1 auto',\n }}\n >\n <span\n style={{\n marginRight: 8,\n fontSize: '12px',\n color: theme.palette.text.secondary,\n flex: 1,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n }}\n >\n {filters.length ? `${filters.length} items` : 'All'}\n </span>\n <button\n onClick={(e) => {\n handleFilterClick(e, column.accessorKey as string);\n }}\n style={{\n border: `1px solid ${theme.palette.divider}`,\n background: theme.palette.background.paper,\n cursor: 'pointer',\n fontSize: '12px',\n color: filters.length ? theme.palette.primary.main : theme.palette.text.secondary,\n padding: '4px 8px',\n borderRadius: '4px',\n minWidth: '20px',\n height: '24px',\n flexShrink: 0,\n transition: 'all 0.2s ease',\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.background = theme.palette.action.hover;\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.background = theme.palette.background.paper;\n }}\n type=\"button\"\n >\n ▼\n </button>\n\n {openFilterColumn === column.accessorKey && (\n <div\n style={{\n position: 'absolute',\n top: '100%',\n left: 0,\n zIndex: 1000,\n marginTop: 4,\n }}\n >\n <ColumnFilterDropdown\n allValues={columnUniqueValues[column.accessorKey as string] || []}\n selectedValues={filters}\n onFilterChange={(values) => updateColumnFilter(column.accessorKey as string, values)}\n theme={theme}\n />\n </div>\n )}\n </div>\n );\n })}\n </div>\n )}\n <Table\n data={filteredData}\n columns={columns}\n cellConfigs={cellConfigs}\n height={spec.enableFiltering ? contentDimensions.height - 40 : contentDimensions.height}\n width={contentDimensions.width}\n density={spec.density}\n defaultColumnWidth={spec.defaultColumnWidth}\n defaultColumnHeight={spec.defaultColumnHeight}\n sorting={sorting}\n onSortingChange={setSorting}\n pagination={pagination}\n onPaginationChange={setPagination}\n checkboxSelection={selectionEnabled}\n rowSelection={rowSelection}\n onRowSelectionChange={handleRowSelectionChange}\n getItemActions={({ id, data }) => getItemActionButtons({ id, data: data as Record<string, unknown> })}\n hasItemActions={actionButtons && actionButtons.length > 0}\n />\n </>\n );\n}\n"],"names":["Box","Typography","useTheme","Table","useSelection","formatValue","transformData","useSelectionItemActions","replaceVariablesInString","useAllVariableValues","useCallback","useEffect","useMemo","useRef","useState","evaluateConditionalFormatting","buildRawTableData","getTablePanelQueryMode","EmbeddedPanel","generateCellContentConfig","column","plugin","undefined","cell","ctx","panelData","getValue","kind","spec","queryResults","cellDescription","cellValue","format","ColumnFilterDropdown","allValues","selectedValues","onFilterChange","theme","values","Set","filter","v","sort","length","div","data-filter-dropdown","style","width","padding","backgroundColor","palette","background","paper","border","divider","borderRadius","boxShadow","shadows","color","text","secondary","fontSize","maxHeight","overflowY","marginBottom","fontWeight","label","display","alignItems","cursor","input","type","checked","onChange","e","target","marginRight","span","primary","hr","margin","borderTop","map","value","index","onMouseEnter","currentTarget","action","hover","onMouseLeave","includes","String","generateColumnConfig","name","columnSettings","allVariables","hide","header","headerDescription","enableSorting","align","dataLink","modifiedDataLink","url","accessorKey","getTablePanelQueryOptions","mode","TablePanel","contentDimensions","selectionEnabled","selection","enabled","selectionMap","setSelection","clearSelection","itemActionsConfig","actions","itemActionsListConfig","displayWithItem","actionsList","getItemActionButtons","confirmDialog","actionButtons","variableState","filteredDataRef","rowSelection","result","forEach","_","id","handleRowSelectionChange","newRowSelection","newSelection","isSelected","Object","entries","parseInt","current","push","item","rawData","data","transforms","keys","entry","key","columnUniqueValues","uniqueValues","row","val","Array","from","columns","customizedColumns","columnSetting","has","columnConfig","add","defaultColumnHidden","cellConfigs","cellSettings","some","col","keysAsObj","reduce","acc","extendRow","cellConfig","find","columnCellConfig","generateDefaultSortingState","desc","sorting","setSorting","columnFilters","setColumnFilters","filterAnchorEl","setFilterAnchorEl","openFilterColumn","setOpenFilterColumn","getSelectedFilterValues","columnId","f","updateColumnFilter","newFilters","handleFilterClick","event","preventDefault","stopPropagation","handleFilterClose","handleClick","closest","timer","setTimeout","document","addEventListener","clearTimeout","removeEventListener","filteredData","filtered","enableFiltering","every","filterValues","pagination","setPagination","pageIndex","pageSize","sx","justifyContent","height","default","borderBottom","boxSizing","idx","filters","columnWidth","defaultColumnWidth","borderRight","minWidth","maxWidth","position","flex","overflow","textOverflow","whiteSpace","button","onClick","main","flexShrink","transition","top","left","zIndex","marginTop","density","defaultColumnHeight","onSortingChange","onPaginationChange","checkboxSelection","onRowSelectionChange","getItemActions","hasItemActions"],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ import { TimeSeriesData } from '@perses-dev/core';
2
+ import { PanelData } from '@perses-dev/plugin-system';
3
+ import { TableOptions } from './models';
4
+ /**
5
+ * Options for building raw table data.
6
+ */
7
+ export interface BuildRawTableDataOptions {
8
+ /**
9
+ * When true, always use raw scalar values for cell data (for export).
10
+ * When false, plugin columns will contain embedded PanelData objects (for rendering).
11
+ */
12
+ forExport?: boolean;
13
+ }
14
+ /**
15
+ * Determines the query mode based on table options.
16
+ * If any column has a plugin (embedded panel), use range mode; otherwise instant.
17
+ */
18
+ export declare function getTablePanelQueryMode(spec: TableOptions): 'instant' | 'range';
19
+ /**
20
+ * Converts raw query results into a tabular format.
21
+ *
22
+ * This is the shared data-building logic used by both TablePanel (for rendering)
23
+ * and TableExportAction (for CSV export). Extracting this ensures both use the
24
+ * same transformation logic, reducing drift.
25
+ *
26
+ * @param queryResults - The panel query results containing time series data
27
+ * @param spec - The table options specification
28
+ * @param options - Build options (e.g., forExport mode)
29
+ * @returns Array of row objects with column keys and values
30
+ */
31
+ export declare function buildRawTableData(queryResults: Array<PanelData<TimeSeriesData>>, spec: TableOptions, options?: BuildRawTableDataOptions): Array<Record<string, unknown>>;
32
+ //# sourceMappingURL=table-data-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"table-data-utils.d.ts","sourceRoot":"","sources":["../../src/table-data-utils.ts"],"names":[],"mappings":"AAaA,OAAO,EAAsB,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACtE,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAExC;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,YAAY,GAAG,SAAS,GAAG,OAAO,CAE9E;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAC/B,YAAY,EAAE,KAAK,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC,EAC9C,IAAI,EAAE,YAAY,EAClB,OAAO,GAAE,wBAA6B,GACrC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CA2ChC"}