diff --git a/packages/grafana-data/src/field/overrides/processors.ts b/packages/grafana-data/src/field/overrides/processors.ts index 9d318b6a3ac..bff63a677f9 100644 --- a/packages/grafana-data/src/field/overrides/processors.ts +++ b/packages/grafana-data/src/field/overrides/processors.ts @@ -15,10 +15,10 @@ export interface NumberFieldConfigSettings { export const numberOverrideProcessor = ( value: any, context: FieldOverrideContext, - settings: NumberFieldConfigSettings + settings?: NumberFieldConfigSettings ) => { const v = parseFloat(`${value}`); - if (settings.max && v > settings.max) { + if (settings && settings.max && v > settings.max) { // ???? } return v; @@ -29,7 +29,7 @@ export interface DataLinksFieldConfigSettings {} export const dataLinksOverrideProcessor = ( value: any, _context: FieldOverrideContext, - _settings: DataLinksFieldConfigSettings + _settings?: DataLinksFieldConfigSettings ) => { return value as DataLink[]; }; @@ -39,7 +39,7 @@ export interface ValueMappingFieldConfigSettings {} export const valueMappingsOverrideProcessor = ( value: any, _context: FieldOverrideContext, - _settings: ValueMappingFieldConfigSettings + _settings?: ValueMappingFieldConfigSettings ) => { return value as ValueMapping[]; // !!!! likely not !!!! }; @@ -51,7 +51,7 @@ export interface SelectFieldConfigSettings { export const selectOverrideProcessor = ( value: any, _context: FieldOverrideContext, - _settings: SelectFieldConfigSettings + _settings?: SelectFieldConfigSettings ) => { return value; }; @@ -65,9 +65,9 @@ export interface StringFieldConfigSettings { export const stringOverrideProcessor = ( value: any, context: FieldOverrideContext, - settings: StringFieldConfigSettings + settings?: StringFieldConfigSettings ) => { - if (settings.expandTemplateVars && context.replaceVariables) { + if (settings && settings.expandTemplateVars && context.replaceVariables) { return context.replaceVariables(value, context.field!.config.scopedVars); } return `${value}`; @@ -80,7 +80,7 @@ export interface ThresholdsFieldConfigSettings { export const thresholdsOverrideProcessor = ( value: any, _context: FieldOverrideContext, - _settings: ThresholdsFieldConfigSettings + _settings?: ThresholdsFieldConfigSettings ) => { return value as ThresholdsConfig; // !!!! likely not !!!! }; @@ -90,7 +90,7 @@ export interface UnitFieldConfigSettings {} export const unitOverrideProcessor = ( value: boolean, _context: FieldOverrideContext, - _settings: UnitFieldConfigSettings + _settings?: UnitFieldConfigSettings ) => { return value; }; @@ -98,7 +98,7 @@ export const unitOverrideProcessor = ( export const booleanOverrideProcessor = ( value: boolean, _context: FieldOverrideContext, - _settings: ThresholdsFieldConfigSettings + _settings?: ThresholdsFieldConfigSettings ) => { return value; // !!!! likely not !!!! }; diff --git a/packages/grafana-data/src/panel/PanelPlugin.test.tsx b/packages/grafana-data/src/panel/PanelPlugin.test.tsx index 70de0912f29..e9244813ed6 100644 --- a/packages/grafana-data/src/panel/PanelPlugin.test.tsx +++ b/packages/grafana-data/src/panel/PanelPlugin.test.tsx @@ -9,7 +9,7 @@ describe('PanelPlugin', () => { return
Panel
; }); - panel.setCustomFieldConfigEditor(builder => { + panel.setCustomFieldOptions(builder => { builder.addCustomEditor({ id: 'custom', name: 'Custom', @@ -31,7 +31,7 @@ describe('PanelPlugin', () => { return
Panel
; }); - panel.setOptionsEditor(builder => { + panel.setPanelOptions(builder => { builder.addCustomEditor({ id: 'option', name: 'Option editor', diff --git a/packages/grafana-data/src/panel/PanelPlugin.ts b/packages/grafana-data/src/panel/PanelPlugin.ts index 1c0271bad7d..0ebf536585b 100644 --- a/packages/grafana-data/src/panel/PanelPlugin.ts +++ b/packages/grafana-data/src/panel/PanelPlugin.ts @@ -110,7 +110,7 @@ export class PanelPlugin extends GrafanaPlugin * interface ShapePanelOptions {} * * export const plugin = new PanelPlugin(ShapePanel) - * .setCustomFieldConfigEditor(builder => { + * .setCustomFieldOptions(builder => { * builder * .addNumberInput({ * id: 'shapeBorderWidth', @@ -134,7 +134,7 @@ export class PanelPlugin extends GrafanaPlugin * * @public **/ - setCustomFieldConfigEditor(builder: (builder: FieldConfigEditorBuilder) => void) { + setCustomFieldOptions(builder: (builder: FieldConfigEditorBuilder) => void) { // builder is applied lazily when custom field configs are accessed this.registerCustomFieldConfigs = builder; return this; @@ -151,7 +151,7 @@ export class PanelPlugin extends GrafanaPlugin * interface ShapePanelOptions {} * * export const plugin = new PanelPlugin(ShapePanel) - * .setOptionsEditor(builder => { + * .setPanelOptions(builder => { * builder * .addSelect({ * id: 'shape', @@ -170,7 +170,7 @@ export class PanelPlugin extends GrafanaPlugin * * @public **/ - setOptionsEditor(builder: (builder: PanelOptionsEditorBuilder) => void) { + setPanelOptions(builder: (builder: PanelOptionsEditorBuilder) => void) { // builder is applied lazily when options UI is created this.registerOptionEditors = builder; return this; diff --git a/packages/grafana-data/src/types/OptionsUIRegistryBuilder.ts b/packages/grafana-data/src/types/OptionsUIRegistryBuilder.ts index 9782582a6fb..7f7a575f9e5 100644 --- a/packages/grafana-data/src/types/OptionsUIRegistryBuilder.ts +++ b/packages/grafana-data/src/types/OptionsUIRegistryBuilder.ts @@ -5,44 +5,46 @@ import { NumberFieldConfigSettings, SelectFieldConfigSettings, StringFieldConfig /** * Option editor registry item */ -interface OptionsEditorItem extends RegistryItem { +export interface OptionsEditorItem extends RegistryItem { + editor: ComponentType; settings?: TSettings; - editor?: ComponentType; } /** * Configuration of option editor registry item */ -type OptionEditorConfig = Pick< - OptionsEditorItem, - 'id' | 'name' | 'description' | 'editor' | 'settings' ->; +interface OptionEditorConfig { + id: string; + name: string; + description: string; + settings?: TSettings; +} /** * Describes an API for option editors UI builder */ export interface OptionsUIRegistryBuilderAPI> { addNumberInput?( - config: OptionEditorConfig + config: OptionEditorConfig ): this; addTextInput?( - config: OptionEditorConfig + config: OptionEditorConfig ): this; addSelect?>( - config: OptionEditorConfig + config: OptionEditorConfig ): this; addRadio? = SelectFieldConfigSettings>( - config: OptionEditorConfig + config: OptionEditorConfig ): this; - addBooleanSwitch?(config: OptionEditorConfig): this; + addBooleanSwitch?(config: OptionEditorConfig): this; - addUnitPicker?(config: OptionEditorConfig): this; + addUnitPicker?(config: OptionEditorConfig): this; - addColorPicker?(config: OptionEditorConfig): this; + addColorPicker?(config: OptionEditorConfig): this; /** * Enables custom editor definition diff --git a/packages/grafana-data/src/types/fieldOverrides.ts b/packages/grafana-data/src/types/fieldOverrides.ts index 48de8ce347d..26e14751af6 100644 --- a/packages/grafana-data/src/types/fieldOverrides.ts +++ b/packages/grafana-data/src/types/fieldOverrides.ts @@ -9,9 +9,10 @@ import { GrafanaTheme, TimeZone, } from '../types'; -import { Registry, RegistryItem } from '../utils'; +import { Registry } from '../utils'; import { InterpolateFunction } from './panel'; import { StandardEditorProps } from '../field'; +import { OptionsEditorItem } from './OptionsUIRegistryBuilder'; export interface DynamicConfigValue { prop: string; @@ -53,24 +54,21 @@ export interface FieldOverrideEditorProps extends Omit - extends Omit, 'id' | 'description' | 'name'>, 'settings'> { +export interface FieldConfigEditorConfig { + id: string; + name: string; + description: string; settings?: TSettings; shouldApply?: (field: Field) => boolean; } -export interface FieldPropertyEditorItem extends RegistryItem { - // An editor the creates the well typed value - editor: ComponentType>; - +export interface FieldPropertyEditorItem + extends OptionsEditorItem> { // An editor that can be filled in with context info (template variables etc) override: ComponentType>; // Convert the override value to a well typed value - process: (value: any, context: FieldOverrideContext, settings: TSettings) => TValue; - - // Configuration options for the particular property - settings: TSettings; + process: (value: any, context: FieldOverrideContext, settings?: TSettings) => TValue; // Checks if field should be processed shouldApply: (field: Field) => boolean; diff --git a/packages/grafana-data/src/types/panel.ts b/packages/grafana-data/src/types/panel.ts index 0e63bc9232b..37defee1989 100644 --- a/packages/grafana-data/src/types/panel.ts +++ b/packages/grafana-data/src/types/panel.ts @@ -1,4 +1,3 @@ -import { ComponentType } from 'react'; import { DataQueryError, DataQueryRequest, DataQueryTimings } from './datasource'; import { PluginMeta } from './plugin'; import { ScopedVars } from './ScopedVars'; @@ -6,8 +5,9 @@ import { LoadingState } from './data'; import { DataFrame } from './dataFrame'; import { AbsoluteTimeRange, TimeRange, TimeZone } from './time'; import { FieldConfigSource } from './fieldOverrides'; -import { Registry, RegistryItem } from '../utils'; +import { Registry } from '../utils'; import { StandardEditorProps } from '../field'; +import { OptionsEditorItem } from './OptionsUIRegistryBuilder'; export type InterpolateFunction = (value: string, scopedVars?: ScopedVars, format?: string | Function) => string; @@ -115,14 +115,16 @@ export type PanelOptionEditorsRegistry = Registry; export interface PanelOptionsEditorProps extends StandardEditorProps {} -export interface PanelOptionsEditorItem extends RegistryItem { - editor: ComponentType>; +export interface PanelOptionsEditorItem + extends OptionsEditorItem> {} + +export interface PanelOptionsEditorConfig { + id: string; + name: string; + description: string; settings?: TSettings; } -export interface PanelOptionsEditorConfig - extends Pick, 'id' | 'description' | 'name' | 'settings'> {} - export interface PanelMenuItem { type?: 'submenu' | 'divider'; text?: string; diff --git a/packages/grafana-ui/src/components/OptionsUI/number.tsx b/packages/grafana-ui/src/components/OptionsUI/number.tsx index fe364588997..692051b1ab9 100644 --- a/packages/grafana-ui/src/components/OptionsUI/number.tsx +++ b/packages/grafana-ui/src/components/OptionsUI/number.tsx @@ -16,14 +16,14 @@ export const NumberValueEditor: React.FC { onChange( - settings.integer ? toIntegerOrUndefined(e.currentTarget.value) : toFloatOrUndefined(e.currentTarget.value) + settings?.integer ? toIntegerOrUndefined(e.currentTarget.value) : toFloatOrUndefined(e.currentTarget.value) ); }} /> diff --git a/packages/grafana-ui/src/components/OptionsUI/select.tsx b/packages/grafana-ui/src/components/OptionsUI/select.tsx index f3d9dfc8d7e..5ca25dc85f8 100644 --- a/packages/grafana-ui/src/components/OptionsUI/select.tsx +++ b/packages/grafana-ui/src/components/OptionsUI/select.tsx @@ -7,5 +7,5 @@ export function SelectValueEditor({ onChange, item, }: FieldConfigEditorProps>) { - return defaultValue={value} onChange={e => onChange(e.value)} options={item.settings.options} />; + return defaultValue={value} onChange={e => onChange(e.value)} options={item.settings?.options} />; } diff --git a/packages/grafana-ui/src/components/VizRepeater/VizRepeater.tsx b/packages/grafana-ui/src/components/VizRepeater/VizRepeater.tsx index ac2c4235de7..326d53cd028 100644 --- a/packages/grafana-ui/src/components/VizRepeater/VizRepeater.tsx +++ b/packages/grafana-ui/src/components/VizRepeater/VizRepeater.tsx @@ -13,7 +13,7 @@ interface Props { /** * Render a single value */ - renderValue: (value: V, width: number, height: number, dims: D) => JSX.Element; + renderValue: (props: VizRepeaterRenderValueProps) => JSX.Element; height: number; width: number; source: any; // If this changes, new values will be requested @@ -23,6 +23,14 @@ interface Props { itemSpacing?: number; } +export interface VizRepeaterRenderValueProps { + value: V; + width: number; + height: number; + orientation: VizOrientation; + alignmentFactors: D; +} + interface DefaultProps { itemSpacing: number; } @@ -99,13 +107,14 @@ export class VizRepeater extends PureComponent, State> itemStyles.width = `${vizWidth}px`; itemStyles.height = `${vizHeight}px`; - const dims = getAlignmentFactors ? getAlignmentFactors(values, vizWidth, vizHeight) : ({} as D); + const alignmentFactors = getAlignmentFactors ? getAlignmentFactors(values, vizWidth, vizHeight) : ({} as D); + return (
{values.map((value, index) => { return (
- {renderValue(value, vizWidth, vizHeight, dims)} + {renderValue({ value, width: vizWidth, height: vizHeight, alignmentFactors, orientation })}
); })} diff --git a/packages/grafana-ui/src/components/index.ts b/packages/grafana-ui/src/components/index.ts index fe43908e347..c1d7093ec10 100644 --- a/packages/grafana-ui/src/components/index.ts +++ b/packages/grafana-ui/src/components/index.ts @@ -78,7 +78,7 @@ export { GraphWithLegend } from './Graph/GraphWithLegend'; export { GraphContextMenu } from './Graph/GraphContextMenu'; export { BarGauge, BarGaugeDisplayMode } from './BarGauge/BarGauge'; export { GraphTooltipOptions } from './Graph/GraphTooltip/types'; -export { VizRepeater } from './VizRepeater/VizRepeater'; +export { VizRepeater, VizRepeaterRenderValueProps } from './VizRepeater/VizRepeater'; export { LegendOptions, diff --git a/public/app/features/dashboard/components/PanelEditor/PanelEditor.tsx b/public/app/features/dashboard/components/PanelEditor/PanelEditor.tsx index 502b4d94aa5..82ecb7d0b97 100644 --- a/public/app/features/dashboard/components/PanelEditor/PanelEditor.tsx +++ b/public/app/features/dashboard/components/PanelEditor/PanelEditor.tsx @@ -315,6 +315,7 @@ export const PanelEditor = connect(mapStateToProps, mapDispatchToProps)(PanelEdi */ const getStyles = stylesFactory((theme: GrafanaTheme) => { const handleColor = theme.colors.blueLight; + const paneSpaceing = theme.spacing.md; const resizer = css` font-style: italic; @@ -354,21 +355,21 @@ const getStyles = stylesFactory((theme: GrafanaTheme) => { `, panelWrapper: css` width: 100%; - padding-left: ${theme.spacing.sm}; + padding-left: ${paneSpaceing}; height: 100%; `, resizerV: cx( resizer, css` cursor: col-resize; - width: 8px; + width: ${paneSpaceing}; border-right-width: 1px; ` ), resizerH: cx( resizer, css` - height: 8px; + height: ${paneSpaceing}; cursor: row-resize; position: relative; top: 49px; diff --git a/public/app/plugins/panel/bargauge/BarGaugePanel.tsx b/public/app/plugins/panel/bargauge/BarGaugePanel.tsx index 8170233a795..47225113687 100644 --- a/public/app/plugins/panel/bargauge/BarGaugePanel.tsx +++ b/public/app/plugins/panel/bargauge/BarGaugePanel.tsx @@ -4,7 +4,7 @@ import React, { PureComponent } from 'react'; // Services & Utils import { config } from 'app/core/config'; -import { BarGauge, VizRepeater, DataLinksContextMenu } from '@grafana/ui'; +import { BarGauge, VizRepeater, VizRepeaterRenderValueProps, DataLinksContextMenu } from '@grafana/ui'; import { BarGaugeOptions } from './types'; import { getFieldDisplayValues, @@ -16,13 +16,9 @@ import { import { getFieldLinksSupplier } from 'app/features/panel/panellinks/linkSuppliers'; export class BarGaugePanel extends PureComponent> { - renderValue = ( - value: FieldDisplay, - width: number, - height: number, - alignmentFactors: DisplayValueAlignmentFactors - ): JSX.Element => { + renderValue = (valueProps: VizRepeaterRenderValueProps): JSX.Element => { const { options } = this.props; + const { value, alignmentFactors, orientation, width, height } = valueProps; const { field, display, view, colIndex } = value; return ( @@ -33,7 +29,7 @@ export class BarGaugePanel extends PureComponent> { value={display} width={width} height={height} - orientation={options.orientation} + orientation={orientation} field={field} display={view?.getFieldDisplayProcessor(colIndex)} theme={config.theme} diff --git a/public/app/plugins/panel/bargauge/BarGaugePanelEditor.tsx b/public/app/plugins/panel/bargauge/BarGaugePanelEditor.tsx index cacd8f3a2e7..eddb8b5dd79 100644 --- a/public/app/plugins/panel/bargauge/BarGaugePanelEditor.tsx +++ b/public/app/plugins/panel/bargauge/BarGaugePanelEditor.tsx @@ -95,6 +95,10 @@ export class BarGaugePanelEditor extends PureComponent {useNewEditor => { + if (useNewEditor) { + return null; + } + return ( <> @@ -135,38 +139,28 @@ export class BarGaugePanelEditor extends PureComponent - <> - {!useNewEditor && ( - <> - - - - - - - )} - - - - {!useNewEditor && ( - - )} - - {!useNewEditor && ( - - + - )} + + + + + + + + + ); }} diff --git a/public/app/plugins/panel/bargauge/module.tsx b/public/app/plugins/panel/bargauge/module.tsx index 5512bd52fff..8d97b815f3c 100644 --- a/public/app/plugins/panel/bargauge/module.tsx +++ b/public/app/plugins/panel/bargauge/module.tsx @@ -1,14 +1,30 @@ import { sharedSingleStatPanelChangedHandler } from '@grafana/ui'; import { PanelPlugin } from '@grafana/data'; import { BarGaugePanel } from './BarGaugePanel'; -import { BarGaugePanelEditor } from './BarGaugePanelEditor'; import { BarGaugeOptions, defaults } from './types'; import { standardFieldConfig } from '../stat/types'; +import { BarGaugePanelEditor } from './BarGaugePanelEditor'; import { barGaugePanelMigrationHandler } from './BarGaugeMigrations'; export const plugin = new PanelPlugin(BarGaugePanel) .setDefaults(defaults) - .setFieldConfigDefaults(standardFieldConfig) .setEditor(BarGaugePanelEditor) + .setFieldConfigDefaults(standardFieldConfig) + .setPanelOptions(builder => { + /* addStandardSingleValueOptions(builder); */ + + builder.addRadio({ + id: 'orientation', + name: 'Orientation', + description: 'Stacking direction for multiple bars', + settings: { + options: [ + { value: 'auto', label: 'Auto' }, + { value: 'horizontal', label: 'Horizontal' }, + { value: 'vertical', label: 'Vertical' }, + ], + }, + }); + }) .setPanelChangeHandler(sharedSingleStatPanelChangedHandler) .setMigrationHandler(barGaugePanelMigrationHandler); diff --git a/public/app/plugins/panel/gauge/GaugePanel.tsx b/public/app/plugins/panel/gauge/GaugePanel.tsx index 585d21df83b..b84bea49533 100644 --- a/public/app/plugins/panel/gauge/GaugePanel.tsx +++ b/public/app/plugins/panel/gauge/GaugePanel.tsx @@ -5,17 +5,17 @@ import React, { PureComponent } from 'react'; import { config } from 'app/core/config'; // Components -import { Gauge, DataLinksContextMenu } from '@grafana/ui'; +import { Gauge, DataLinksContextMenu, VizRepeater, VizRepeaterRenderValueProps } from '@grafana/ui'; // Types import { GaugeOptions } from './types'; -import { VizRepeater } from '@grafana/ui'; import { FieldDisplay, getFieldDisplayValues, VizOrientation, PanelProps } from '@grafana/data'; import { getFieldLinksSupplier } from 'app/features/panel/panellinks/linkSuppliers'; export class GaugePanel extends PureComponent> { - renderValue = (value: FieldDisplay, width: number, height: number): JSX.Element => { + renderValue = (valueProps: VizRepeaterRenderValueProps): JSX.Element => { const { options } = this.props; + const { value, width, height } = valueProps; const { field, display } = value; return ( diff --git a/public/app/plugins/panel/stat/StatPanel.tsx b/public/app/plugins/panel/stat/StatPanel.tsx index 7ae461e0c3c..32ffefa2574 100644 --- a/public/app/plugins/panel/stat/StatPanel.tsx +++ b/public/app/plugins/panel/stat/StatPanel.tsx @@ -6,7 +6,14 @@ import { config } from 'app/core/config'; // Types import { StatPanelOptions } from './types'; -import { VizRepeater, BigValue, DataLinksContextMenu, BigValueSparkline, BigValueGraphMode } from '@grafana/ui'; +import { + VizRepeater, + VizRepeaterRenderValueProps, + BigValue, + DataLinksContextMenu, + BigValueSparkline, + BigValueGraphMode, +} from '@grafana/ui'; import { PanelProps, @@ -21,13 +28,9 @@ import { import { getFieldLinksSupplier } from 'app/features/panel/panellinks/linkSuppliers'; export class StatPanel extends PureComponent> { - renderValue = ( - value: FieldDisplay, - width: number, - height: number, - alignmentFactors: DisplayValueAlignmentFactors - ): JSX.Element => { + renderValue = (valueProps: VizRepeaterRenderValueProps): JSX.Element => { const { timeRange, options } = this.props; + const { value, alignmentFactors, width, height } = valueProps; let sparkline: BigValueSparkline | undefined; if (value.sparkline) { diff --git a/public/app/plugins/panel/stat/types.ts b/public/app/plugins/panel/stat/types.ts index e90d16bed27..d65447bf931 100644 --- a/public/app/plugins/panel/stat/types.ts +++ b/public/app/plugins/panel/stat/types.ts @@ -7,6 +7,7 @@ import { FieldConfigSource, ThresholdsMode, } from '@grafana/data'; +import { PanelOptionsEditorBuilder } from '@grafana/data/src/utils/OptionsUIBuilders'; // Structure copied from angular export interface StatPanelOptions extends SingleStatBaseOptions { @@ -49,6 +50,20 @@ export const standardFieldConfig: FieldConfigSource = { overrides: [], }; +export function addStandardSingleValueOptions(builder: PanelOptionsEditorBuilder) { + builder.addRadio({ + id: 'values', + name: 'Show', + description: 'Calculate a single value per colum or series or show each row', + settings: { + options: [ + { value: false, label: 'Calculate' }, + { value: true, label: 'All values' }, + ], + }, + }); +} + export const defaults: StatPanelOptions = { graphMode: BigValueGraphMode.Area, colorMode: BigValueColorMode.Value, diff --git a/public/app/plugins/panel/table2/TablePanel.tsx b/public/app/plugins/panel/table2/TablePanel.tsx index 4021c26b4ba..ea01b9c772d 100644 --- a/public/app/plugins/panel/table2/TablePanel.tsx +++ b/public/app/plugins/panel/table2/TablePanel.tsx @@ -8,20 +8,18 @@ import { Options } from './types'; interface Props extends PanelProps {} -const paddingBottom = 16; - export class TablePanel extends Component { constructor(props: Props) { super(props); } render() { - const { data, height, width } = this.props; + const { data, height, width, options } = this.props; if (data.series.length < 1) { return
No Table Data...
; } - return ; + return
; } } diff --git a/public/app/plugins/panel/table2/module.tsx b/public/app/plugins/panel/table2/module.tsx index 5524e3b17a8..ee4839dbeaf 100644 --- a/public/app/plugins/panel/table2/module.tsx +++ b/public/app/plugins/panel/table2/module.tsx @@ -4,7 +4,7 @@ import { Options, defaults } from './types'; export const plugin = new PanelPlugin(TablePanel) .setDefaults(defaults) - .setCustomFieldConfigEditor(builder => { + .setCustomFieldOptions(builder => { builder .addNumberInput({ id: 'width', @@ -20,7 +20,6 @@ export const plugin = new PanelPlugin(TablePanel) id: 'displayMode', name: 'Cell display mode', description: 'Color value, background, show as gauge, etc', - settings: { options: [ { value: 'auto', label: 'Auto' }, @@ -31,7 +30,7 @@ export const plugin = new PanelPlugin(TablePanel) }, }); }) - .setOptionsEditor(builder => { + .setPanelOptions(builder => { builder.addBooleanSwitch({ id: 'showHeader', name: 'Show header',