chore: pull in table options
This commit is contained in:
@@ -1,10 +1,11 @@
|
||||
import { css } from '@emotion/css';
|
||||
import { useEffect, useState, useMemo } from 'react';
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { lastValueFrom } from 'rxjs';
|
||||
|
||||
import {
|
||||
applyFieldOverrides,
|
||||
DataFrame,
|
||||
FieldConfigSource,
|
||||
GrafanaTheme2,
|
||||
PanelProps,
|
||||
transformDataFrame,
|
||||
@@ -23,16 +24,23 @@ import {
|
||||
LogsFrame,
|
||||
parseLogsFrame,
|
||||
} from '../../../features/logs/logsFrame';
|
||||
import { isSetDisplayedFields } from '../logs/types';
|
||||
import { TablePanel } from '../table/TablePanel';
|
||||
import type { Options as TableOptions } from '../table/panelcfg.gen';
|
||||
|
||||
import type { Options } from './panelcfg.gen';
|
||||
import type { Options as LogsTableOptions } from './panelcfg.gen';
|
||||
import { isOnLogsTableOptionsChange, onLogsTableOptionsChangeType } from './types';
|
||||
|
||||
interface LogsTablePanelProps extends PanelProps<Options> {
|
||||
interface LogsTablePanelProps extends PanelProps<LogsTableOptions> {
|
||||
frameIndex?: number;
|
||||
showHeader?: boolean;
|
||||
}
|
||||
|
||||
// keeping alias @todo remove
|
||||
//@ts-expect-error
|
||||
const a: TableOptions = {};
|
||||
console.log('a', a);
|
||||
|
||||
const sidebarWidth = 200;
|
||||
|
||||
export const LogsTable = ({
|
||||
@@ -55,7 +63,10 @@ export const LogsTable = ({
|
||||
id,
|
||||
renderCounter,
|
||||
}: LogsTablePanelProps) => {
|
||||
// Variables
|
||||
const dataFrame = data.series[frameIndex];
|
||||
|
||||
// Hooks
|
||||
const logsFrame: LogsFrame | null = useMemo(() => parseLogsFrame(dataFrame), [dataFrame]);
|
||||
const defaultDisplayedFields = useMemo(
|
||||
() => [
|
||||
@@ -65,18 +76,54 @@ export const LogsTable = ({
|
||||
[logsFrame?.timeField.name, logsFrame?.bodyField.name]
|
||||
);
|
||||
|
||||
// State
|
||||
const [extractedFrame, setExtractedFrame] = useState<DataFrame[] | null>(null);
|
||||
const [organizedFrame, setOrganizedFrame] = useState<DataFrame[] | null>(null);
|
||||
const [displayedFields, setDisplayedFields] = useState<string[]>(options.displayedFields ?? defaultDisplayedFields);
|
||||
const styles = useStyles2(getStyles, sidebarWidth, height, width);
|
||||
const dataLinksContext = useDataLinksContext();
|
||||
|
||||
const onTableOptionsChange = (options: TableOptions) => {
|
||||
onOptionsChange({});
|
||||
};
|
||||
|
||||
const unTransformedDataFrame = data.series[frameIndex];
|
||||
|
||||
// Methods
|
||||
const onLogsTableOptionsChange: onLogsTableOptionsChangeType | undefined = isOnLogsTableOptionsChange(onOptionsChange)
|
||||
? onOptionsChange
|
||||
: undefined;
|
||||
|
||||
const setDisplayedFieldsFn = isSetDisplayedFields(options.setDisplayedFields)
|
||||
? options.setDisplayedFields
|
||||
: setDisplayedFields;
|
||||
|
||||
const onTableOptionsChange = useCallback(
|
||||
(options: TableOptions) => {
|
||||
console.log('onTableOptionsChange', options);
|
||||
onLogsTableOptionsChange?.(options);
|
||||
},
|
||||
[onLogsTableOptionsChange]
|
||||
);
|
||||
|
||||
const handleLogsTableOptionsChange = useCallback(
|
||||
(options: LogsTableOptions) => {
|
||||
onOptionsChange(options);
|
||||
},
|
||||
[onOptionsChange]
|
||||
);
|
||||
|
||||
const handleSetDisplayedFields = useCallback(
|
||||
(displayedFields: string[]) => {
|
||||
setDisplayedFieldsFn(displayedFields);
|
||||
handleLogsTableOptionsChange({ ...options, displayedFields: displayedFields });
|
||||
},
|
||||
[handleLogsTableOptionsChange, options, setDisplayedFieldsFn]
|
||||
);
|
||||
|
||||
const handleTableOnFieldConfigChange = useCallback(
|
||||
(fieldConfig: FieldConfigSource) => {
|
||||
console.log('onTableOnFieldConfigChange', fieldConfig);
|
||||
onFieldConfigChange(fieldConfig);
|
||||
},
|
||||
[onFieldConfigChange]
|
||||
);
|
||||
|
||||
/**
|
||||
* Extract fields transform
|
||||
*/
|
||||
@@ -91,10 +138,7 @@ export const LogsTable = ({
|
||||
setExtractedFrame(
|
||||
applyFieldOverrides({
|
||||
data: frame,
|
||||
fieldConfig: {
|
||||
defaults: {},
|
||||
overrides: [],
|
||||
},
|
||||
fieldConfig,
|
||||
replaceVariables: getTemplateSrv().replace.bind(getTemplateSrv()),
|
||||
theme: config.theme2,
|
||||
timeZone: timeZone,
|
||||
@@ -102,7 +146,7 @@ export const LogsTable = ({
|
||||
})
|
||||
);
|
||||
});
|
||||
}, [dataLinksContext.dataLinkPostProcessor, timeZone, unTransformedDataFrame]);
|
||||
}, [dataLinksContext.dataLinkPostProcessor, fieldConfig, timeZone, unTransformedDataFrame]);
|
||||
|
||||
/**
|
||||
* Organize fields transform
|
||||
@@ -164,9 +208,9 @@ export const LogsTable = ({
|
||||
sidebarWidth={sidebarWidth}
|
||||
toggle={(key: string) => {
|
||||
if (displayedFields.includes(key)) {
|
||||
setDisplayedFields(displayedFields.filter((f) => f !== key));
|
||||
handleSetDisplayedFields(displayedFields.filter((f) => f !== key));
|
||||
} else {
|
||||
setDisplayedFields([...displayedFields, key]);
|
||||
handleSetDisplayedFields([...displayedFields, key]);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
@@ -186,7 +230,7 @@ export const LogsTable = ({
|
||||
title={title}
|
||||
eventBus={eventBus}
|
||||
onOptionsChange={onTableOptionsChange}
|
||||
onFieldConfigChange={onFieldConfigChange}
|
||||
onFieldConfigChange={handleTableOnFieldConfigChange}
|
||||
replaceVariables={replaceVariables}
|
||||
onChangeTimeRange={onChangeTimeRange}
|
||||
/>
|
||||
|
||||
@@ -1,54 +1,233 @@
|
||||
import { PanelPlugin } from '@grafana/data';
|
||||
import { FieldConfigProperty, identityOverrideProcessor, PanelPlugin, standardEditorsRegistry } from '@grafana/data';
|
||||
import { t } from '@grafana/i18n';
|
||||
import {
|
||||
TableCellDisplayMode,
|
||||
TableCellHeight,
|
||||
TableCellOptions,
|
||||
TableCellTooltipPlacement,
|
||||
} from '@grafana/schema/dist/esm/common/common.gen';
|
||||
import { defaultTableFieldOptions } from '@grafana/schema/dist/esm/veneer/common.types';
|
||||
|
||||
import { PaginationEditor } from '../table/PaginationEditor';
|
||||
import { TableCellOptionEditor } from '../table/TableCellOptionEditor';
|
||||
import { tablePanelChangedHandler } from '../table/migrations';
|
||||
import { defaultOptions, FieldConfig as TableFieldConfig } from '../table/panelcfg.gen';
|
||||
import { tableSuggestionsSupplier } from '../table/suggestions';
|
||||
|
||||
import { LogsTable } from './LogsTable';
|
||||
import { Options } from './panelcfg.gen';
|
||||
|
||||
export const plugin = new PanelPlugin<Options>(LogsTable).setPanelOptions((builder) => {
|
||||
builder.addBooleanSwitch({
|
||||
path: 'wrapLogMessage',
|
||||
name: 'Wrap lines',
|
||||
description: '',
|
||||
defaultValue: false,
|
||||
});
|
||||
|
||||
// @todo add table options?
|
||||
//
|
||||
// .addRadio({
|
||||
// path: 'dedupStrategy',
|
||||
// name: 'Deduplication',
|
||||
// description: '',
|
||||
// settings: {
|
||||
// options: [
|
||||
// { value: LogsDedupStrategy.none, label: 'None', description: LogsDedupDescription[LogsDedupStrategy.none] },
|
||||
// {
|
||||
// value: LogsDedupStrategy.exact,
|
||||
// label: 'Exact',
|
||||
// description: LogsDedupDescription[LogsDedupStrategy.exact],
|
||||
// },
|
||||
// {
|
||||
// value: LogsDedupStrategy.numbers,
|
||||
// label: 'Numbers',
|
||||
// description: LogsDedupDescription[LogsDedupStrategy.numbers],
|
||||
// },
|
||||
// {
|
||||
// value: LogsDedupStrategy.signature,
|
||||
// label: 'Signature',
|
||||
// description: LogsDedupDescription[LogsDedupStrategy.signature],
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
// defaultValue: LogsDedupStrategy.none,
|
||||
// })
|
||||
// .addRadio({
|
||||
// path: 'sortOrder',
|
||||
// name: 'Order',
|
||||
// description: '',
|
||||
// settings: {
|
||||
// options: [
|
||||
// { value: LogsSortOrder.Descending, label: 'Newest first' },
|
||||
// { value: LogsSortOrder.Ascending, label: 'Oldest first' },
|
||||
// ],
|
||||
// },
|
||||
// defaultValue: LogsSortOrder.Descending,
|
||||
// });
|
||||
});
|
||||
export const plugin = new PanelPlugin<Options, TableFieldConfig>(LogsTable)
|
||||
.setPanelChangeHandler(tablePanelChangedHandler)
|
||||
.useFieldConfig({
|
||||
standardOptions: {
|
||||
[FieldConfigProperty.Actions]: {
|
||||
hideFromDefaults: false,
|
||||
},
|
||||
},
|
||||
useCustomConfig: (builder) => {
|
||||
const category = [t('table.category-logs-table', 'Logs Table')];
|
||||
const cellCategory = [t('table.category-cell-options', 'Cell options')];
|
||||
builder
|
||||
.addNumberInput({
|
||||
path: 'minWidth',
|
||||
name: t('table.name-min-column-width', 'Minimum column width'),
|
||||
category,
|
||||
description: t('table.description-min-column-width', 'The minimum width for column auto resizing'),
|
||||
settings: {
|
||||
placeholder: '150',
|
||||
min: 50,
|
||||
max: 500,
|
||||
},
|
||||
shouldApply: () => true,
|
||||
defaultValue: defaultTableFieldOptions.minWidth,
|
||||
})
|
||||
.addNumberInput({
|
||||
path: 'width',
|
||||
name: t('table.name-column-width', 'Column width'),
|
||||
category,
|
||||
settings: {
|
||||
placeholder: t('table.placeholder-column-width', 'auto'),
|
||||
min: 20,
|
||||
},
|
||||
shouldApply: () => true,
|
||||
defaultValue: defaultTableFieldOptions.width,
|
||||
})
|
||||
.addRadio({
|
||||
path: 'align',
|
||||
name: t('table.name-column-alignment', 'Column alignment'),
|
||||
category,
|
||||
settings: {
|
||||
options: [
|
||||
{ label: t('table.column-alignment-options.label-auto', 'Auto'), value: 'auto' },
|
||||
{ label: t('table.column-alignment-options.label-left', 'Left'), value: 'left' },
|
||||
{ label: t('table.column-alignment-options.label-center', 'Center'), value: 'center' },
|
||||
{ label: t('table.column-alignment-options.label-right', 'Right'), value: 'right' },
|
||||
],
|
||||
},
|
||||
defaultValue: defaultTableFieldOptions.align,
|
||||
})
|
||||
.addBooleanSwitch({
|
||||
path: 'filterable',
|
||||
name: t('table.name-column-filter', 'Column filter'),
|
||||
category,
|
||||
description: t('table.description-column-filter', 'Enables/disables field filters in table'),
|
||||
defaultValue: defaultTableFieldOptions.filterable,
|
||||
})
|
||||
.addBooleanSwitch({
|
||||
path: 'wrapText',
|
||||
name: t('table.name-wrap-text', 'Wrap text'),
|
||||
category,
|
||||
})
|
||||
.addBooleanSwitch({
|
||||
path: 'wrapHeaderText',
|
||||
name: t('table.name-wrap-header-text', 'Wrap header text'),
|
||||
category,
|
||||
})
|
||||
.addBooleanSwitch({
|
||||
path: 'hideFrom.viz',
|
||||
name: t('table.name-hide-in-table', 'Hide in table'),
|
||||
category,
|
||||
defaultValue: undefined,
|
||||
hideFromDefaults: true,
|
||||
})
|
||||
.addCustomEditor({
|
||||
id: 'footer.reducers',
|
||||
category: [t('table.category-table-footer', 'Table footer')],
|
||||
path: 'footer.reducers',
|
||||
name: t('table.name-calculation', 'Calculation'),
|
||||
description: t('table.description-calculation', 'Choose a reducer function / calculation'),
|
||||
editor: standardEditorsRegistry.get('stats-picker').editor,
|
||||
override: standardEditorsRegistry.get('stats-picker').editor,
|
||||
defaultValue: [],
|
||||
process: identityOverrideProcessor,
|
||||
shouldApply: () => true,
|
||||
settings: {
|
||||
allowMultiple: true,
|
||||
},
|
||||
})
|
||||
.addCustomEditor<void, TableCellOptions>({
|
||||
id: 'cellOptions',
|
||||
path: 'cellOptions',
|
||||
name: t('table.name-cell-type', 'Cell type'),
|
||||
editor: TableCellOptionEditor,
|
||||
override: TableCellOptionEditor,
|
||||
defaultValue: defaultTableFieldOptions.cellOptions,
|
||||
process: identityOverrideProcessor,
|
||||
category: cellCategory,
|
||||
shouldApply: () => true,
|
||||
})
|
||||
.addBooleanSwitch({
|
||||
path: 'inspect',
|
||||
name: t('table.name-cell-value-inspect', 'Cell value inspect'),
|
||||
description: t('table.description-cell-value-inspect', 'Enable cell value inspection in a modal window'),
|
||||
defaultValue: false,
|
||||
category: cellCategory,
|
||||
showIf: (cfg) => {
|
||||
return (
|
||||
cfg.cellOptions.type === TableCellDisplayMode.Auto ||
|
||||
cfg.cellOptions.type === TableCellDisplayMode.JSONView ||
|
||||
cfg.cellOptions.type === TableCellDisplayMode.ColorText ||
|
||||
cfg.cellOptions.type === TableCellDisplayMode.ColorBackground
|
||||
);
|
||||
},
|
||||
})
|
||||
.addFieldNamePicker({
|
||||
path: 'tooltip.field',
|
||||
name: t('table.name-tooltip-from-field', 'Tooltip from field'),
|
||||
description: t(
|
||||
'table.description-tooltip-from-field',
|
||||
'Render a cell from a field (hidden or visible) in a tooltip'
|
||||
),
|
||||
category: cellCategory,
|
||||
})
|
||||
.addSelect({
|
||||
path: 'tooltip.placement',
|
||||
name: t('table.name-tooltip-placement', 'Tooltip placement'),
|
||||
category: cellCategory,
|
||||
settings: {
|
||||
options: [
|
||||
{
|
||||
label: t('table.tooltip-placement-options.label-auto', 'Auto'),
|
||||
value: TableCellTooltipPlacement.Auto,
|
||||
},
|
||||
{
|
||||
label: t('table.tooltip-placement-options.label-top', 'Top'),
|
||||
value: TableCellTooltipPlacement.Top,
|
||||
},
|
||||
{
|
||||
label: t('table.tooltip-placement-options.label-right', 'Right'),
|
||||
value: TableCellTooltipPlacement.Right,
|
||||
},
|
||||
{
|
||||
label: t('table.tooltip-placement-options.label-bottom', 'Bottom'),
|
||||
value: TableCellTooltipPlacement.Bottom,
|
||||
},
|
||||
{
|
||||
label: t('table.tooltip-placement-options.label-left', 'Left'),
|
||||
value: TableCellTooltipPlacement.Left,
|
||||
},
|
||||
],
|
||||
},
|
||||
showIf: (cfg) => cfg.tooltip?.field !== undefined,
|
||||
})
|
||||
.addFieldNamePicker({
|
||||
path: 'styleField',
|
||||
name: t('table.name-styling-from-field', 'Styling from field'),
|
||||
description: t('table.description-styling-from-field', 'A field containing JSON objects with CSS properties'),
|
||||
category: cellCategory,
|
||||
});
|
||||
},
|
||||
})
|
||||
.setPanelOptions((builder) => {
|
||||
const category = [t('table.category-table', 'Table')];
|
||||
builder
|
||||
.addBooleanSwitch({
|
||||
path: 'showHeader',
|
||||
name: t('table.name-show-table-header', 'Show table header'),
|
||||
category,
|
||||
defaultValue: defaultOptions.showHeader,
|
||||
})
|
||||
.addNumberInput({
|
||||
path: 'frozenColumns.left',
|
||||
name: t('table.name-frozen-columns', 'Frozen columns'),
|
||||
description: t('table.description-frozen-columns', 'Columns are frozen from the left side of the table'),
|
||||
settings: {
|
||||
placeholder: 'none',
|
||||
},
|
||||
category,
|
||||
})
|
||||
.addRadio({
|
||||
path: 'cellHeight',
|
||||
name: t('table.name-cell-height', 'Cell height'),
|
||||
category,
|
||||
defaultValue: defaultOptions.cellHeight,
|
||||
settings: {
|
||||
options: [
|
||||
{ value: TableCellHeight.Sm, label: t('table.cell-height-options.label-small', 'Small') },
|
||||
{ value: TableCellHeight.Md, label: t('table.cell-height-options.label-medium', 'Medium') },
|
||||
{ value: TableCellHeight.Lg, label: t('table.cell-height-options.label-large', 'Large') },
|
||||
],
|
||||
},
|
||||
})
|
||||
.addNumberInput({
|
||||
path: 'maxRowHeight',
|
||||
name: t('table.name-max-height', 'Max row height'),
|
||||
category,
|
||||
settings: {
|
||||
placeholder: t('table.placeholder-max-height', 'none'),
|
||||
min: 0,
|
||||
},
|
||||
})
|
||||
.addCustomEditor({
|
||||
id: 'enablePagination',
|
||||
path: 'enablePagination',
|
||||
name: t('table.name-enable-pagination', 'Enable pagination'),
|
||||
category,
|
||||
editor: PaginationEditor,
|
||||
defaultValue: defaultOptions?.enablePagination,
|
||||
});
|
||||
})
|
||||
// @todo
|
||||
//@ts-expect-error
|
||||
.setSuggestionsSupplier(tableSuggestionsSupplier);
|
||||
|
||||
@@ -1,2 +1,8 @@
|
||||
// @todo add some stuff
|
||||
export type TODO = string;
|
||||
import type { Options as TableOptions } from '../table/panelcfg.gen';
|
||||
|
||||
import type { Options as LogsTableOptions } from './panelcfg.gen';
|
||||
|
||||
export type onLogsTableOptionsChangeType = (option: LogsTableOptions & TableOptions) => void;
|
||||
export function isOnLogsTableOptionsChange(callback: unknown): callback is onLogsTableOptionsChangeType {
|
||||
return typeof callback === 'function';
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user