mirror of https://github.com/grafana/grafana
Table Panel: Refactor Cell Options to Allow for Options per Cell Type (#59363)
* Update table data structure schema. * Update table panel configuration options for new structure * Fix TS errors from refactor * Separate background and gauge display modes * Remove the now used Bar Gauge display from the mud * Fix types up * Reorganize data structures * Fix type issues. * Start stubbing necessary code. * Continue implementing option refactor * Change category for cell type selection. * Consolidate cell options * Fix various typing issues * Clean up dead code * Stub handling display mode changes * Make subOption editor dynamic * Setup interface for sub-option editor props * Remove unused imports * Remove console.log call * Persist display mode changes, stub sub options change, update comments. * Make sure updates from cells are persisted * Persist sub-option changes * Update BarGaugeCell to take into account new settings. * Add deprecated field back * Remove unecessary options in configuration * Update default cell to accept new settings * Make sure color text display works * Add deprecated property notice * Use constant as opposed to string * Make sure we name globally namespaced things uniquely * Update to use unique name * Use union type with discriminator. * Simplify types and operation * Update type definitons * Update types * Update property names in cells * Remove React.FC usage * Update option editor signature * Update options structure * Change variable name * Fix "Color Text" display * Remove debug statement * Make sure we remain backwards compatible with display mode. * Add migration for configuration. * Export BarGaugeDisplayMode from grafana-ui * Update import * Fix bar gauge and dashboard migrator tests * Fix potential undefined references causing test failures * Fix another potential reference error in DefaultCell * Try to fix breaking change detection. * Cache setting changes * Make sure we return with onChange invocation * Fixed migrating overrides * Fix a number of review comments * Simplify option editors * Fix unused imports * Fill out comments for types * Actually use defaultPanelConfig for editor default * Move TableCellEditorProps alongside TableCellOptionEditor * Update docs for table panel * Also make sure we remove TableCellEditorProps from model file * Stub migration tests * Add tests for default config migration * Add basic overrides test * Flesh out tests a bit more * Add inspect to same category as cell editor Co-authored-by: Torkel Ödegaard <torkel@grafana.com>pull/61359/head^2
parent
d5da42bbbc
commit
80e7f54166
@ -0,0 +1,106 @@ |
||||
import { merge } from 'lodash'; |
||||
import React, { ReactNode, useState } from 'react'; |
||||
|
||||
import { SelectableValue } from '@grafana/data'; |
||||
import { TableCellOptions } from '@grafana/schema'; |
||||
import { Field, HorizontalGroup, Select, TableCellDisplayMode } from '@grafana/ui'; |
||||
|
||||
import { BarGaugeCellOptionsEditor } from './cells/BarGaugeCellOptionsEditor'; |
||||
import { ColorBackgroundCellOptionsEditor } from './cells/ColorBackgroundCellOptionsEditor'; |
||||
|
||||
const cellDisplayModeOptions = [ |
||||
{ value: TableCellDisplayMode.Auto, label: 'Auto' }, |
||||
{ value: TableCellDisplayMode.ColorText, label: 'Colored text' }, |
||||
{ value: TableCellDisplayMode.ColorBackground, label: 'Colored background' }, |
||||
{ value: TableCellDisplayMode.Gauge, label: 'Gauge' }, |
||||
{ value: TableCellDisplayMode.JSONView, label: 'JSON View' }, |
||||
{ value: TableCellDisplayMode.Image, label: 'Image' }, |
||||
]; |
||||
|
||||
// The props that any cell type editor are expected
|
||||
// to handle. In this case the generic type should
|
||||
// be a discriminated interface of TableCellOptions
|
||||
export interface TableCellEditorProps<T> { |
||||
cellOptions: T; |
||||
onChange: (value: T) => void; |
||||
} |
||||
|
||||
// Maps display modes to editor components
|
||||
interface ComponentMap { |
||||
[key: string]: Function; |
||||
} |
||||
|
||||
// Maps cell type to options for caching
|
||||
interface SettingMap { |
||||
[key: string]: TableCellOptions; |
||||
} |
||||
|
||||
/* |
||||
Map of display modes to editor components |
||||
Additional cell types can be placed here |
||||
--- |
||||
A cell editor is expected to be a functional |
||||
component that accepts options and displays |
||||
them in a form. |
||||
*/ |
||||
const displayModeComponentMap: ComponentMap = { |
||||
[TableCellDisplayMode.Gauge]: BarGaugeCellOptionsEditor, |
||||
[TableCellDisplayMode.ColorBackground]: ColorBackgroundCellOptionsEditor, |
||||
}; |
||||
|
||||
interface Props { |
||||
value: TableCellOptions; |
||||
onChange: (v: TableCellOptions) => void; |
||||
} |
||||
|
||||
export const TableCellOptionEditor = ({ value, onChange }: Props) => { |
||||
const cellType = value.type; |
||||
let editor: ReactNode | null = null; |
||||
let [settingCache, setSettingCache] = useState<SettingMap>({}); |
||||
|
||||
// Update display mode on change
|
||||
const onCellTypeChange = (v: SelectableValue<TableCellDisplayMode>) => { |
||||
if (v.value !== undefined) { |
||||
// Set the new type of cell starting
|
||||
// with default settings
|
||||
value = { |
||||
type: v.value, |
||||
}; |
||||
|
||||
// When changing cell type see if there were previously stored
|
||||
// settings and merge those with the changed value
|
||||
if (settingCache[v.value] !== undefined && Object.keys(settingCache[v.value]).length > 1) { |
||||
settingCache[v.value] = merge(value, settingCache[v.value]); |
||||
setSettingCache(settingCache); |
||||
onChange(settingCache[v.value]); |
||||
return; |
||||
} |
||||
|
||||
onChange(value); |
||||
} |
||||
}; |
||||
|
||||
// When options for a cell change we merge
|
||||
// any option changes with our options object
|
||||
const onCellOptionsChange = (options: TableCellOptions) => { |
||||
settingCache[value.type] = merge(value, options); |
||||
setSettingCache(settingCache); |
||||
onChange(settingCache[value.type]); |
||||
}; |
||||
|
||||
// Setup specific cell editor
|
||||
if (cellType !== undefined && displayModeComponentMap[cellType] !== undefined) { |
||||
let Comp: Function = displayModeComponentMap[cellType]; |
||||
editor = <Comp cellOptions={value} onChange={onCellOptionsChange} />; |
||||
} |
||||
|
||||
// Setup and inject editor
|
||||
return ( |
||||
<> |
||||
<Field> |
||||
<Select options={cellDisplayModeOptions} value={cellType} onChange={onCellTypeChange} /> |
||||
</Field> |
||||
<HorizontalGroup>{editor}</HorizontalGroup> |
||||
</> |
||||
); |
||||
}; |
||||
@ -0,0 +1,32 @@ |
||||
import React from 'react'; |
||||
|
||||
import { SelectableValue } from '@grafana/data'; |
||||
import { BarGaugeDisplayMode, TableBarGaugeCellOptions } from '@grafana/schema'; |
||||
import { Field, HorizontalGroup, Select } from '@grafana/ui'; |
||||
|
||||
import { TableCellEditorProps } from '../TableCellOptionEditor'; |
||||
|
||||
const barGaugeOpts: SelectableValue[] = [ |
||||
{ value: BarGaugeDisplayMode.Basic, label: 'Basic' }, |
||||
{ value: BarGaugeDisplayMode.Gradient, label: 'Gradient' }, |
||||
{ value: BarGaugeDisplayMode.Lcd, label: 'Retro LCD' }, |
||||
]; |
||||
|
||||
export const BarGaugeCellOptionsEditor = ({ |
||||
cellOptions, |
||||
onChange, |
||||
}: TableCellEditorProps<TableBarGaugeCellOptions>) => { |
||||
// Set the display mode on change
|
||||
const onCellOptionsChange = (v: SelectableValue) => { |
||||
cellOptions.mode = v.value; |
||||
onChange(cellOptions); |
||||
}; |
||||
|
||||
return ( |
||||
<HorizontalGroup> |
||||
<Field label="Gauge Display Mode"> |
||||
<Select value={cellOptions?.mode} onChange={onCellOptionsChange} options={barGaugeOpts} /> |
||||
</Field> |
||||
</HorizontalGroup> |
||||
); |
||||
}; |
||||
@ -0,0 +1,31 @@ |
||||
import React from 'react'; |
||||
|
||||
import { SelectableValue } from '@grafana/data'; |
||||
import { TableCellBackgroundDisplayMode, TableColoredBackgroundCellOptions } from '@grafana/schema'; |
||||
import { HorizontalGroup, Select, Field } from '@grafana/ui'; |
||||
|
||||
import { TableCellEditorProps } from '../TableCellOptionEditor'; |
||||
|
||||
const colorBackgroundOpts: SelectableValue[] = [ |
||||
{ value: TableCellBackgroundDisplayMode.Basic, label: 'Basic' }, |
||||
{ value: TableCellBackgroundDisplayMode.Gradient, label: 'Gradient' }, |
||||
]; |
||||
|
||||
export const ColorBackgroundCellOptionsEditor = ({ |
||||
cellOptions, |
||||
onChange, |
||||
}: TableCellEditorProps<TableColoredBackgroundCellOptions>) => { |
||||
// Set the display mode on change
|
||||
const onCellOptionsChange = (v: SelectableValue) => { |
||||
cellOptions.mode = v.value; |
||||
onChange(cellOptions); |
||||
}; |
||||
|
||||
return ( |
||||
<HorizontalGroup> |
||||
<Field label="Background display mode"> |
||||
<Select value={cellOptions?.mode} onChange={onCellOptionsChange} options={colorBackgroundOpts} /> |
||||
</Field> |
||||
</HorizontalGroup> |
||||
); |
||||
}; |
||||
Loading…
Reference in new issue