mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
StatPanels: Refactoring DisplayValueOptions and renaming & adding new panel options to react panels (#23153)
* StatPanels: Refactoring DisplayValueOptions and renaming * added return * Progress * Updated * Made radio groups full width by default in panel options * Fixed ts issue * Updated * Added remaining options * Removed unused type * Updated snapshot * Renamed to ReduceDataOptions
This commit is contained in:
parent
8d2db9af7b
commit
53630b5f13
@ -26,7 +26,7 @@ describe('FieldDisplay', () => {
|
||||
|
||||
it('show first numeric values', () => {
|
||||
const options = createDisplayOptions({
|
||||
fieldOptions: {
|
||||
reduceOptions: {
|
||||
calcs: [ReducerID.first],
|
||||
},
|
||||
fieldConfig: {
|
||||
@ -42,7 +42,7 @@ describe('FieldDisplay', () => {
|
||||
|
||||
it('show last numeric values', () => {
|
||||
const options = createDisplayOptions({
|
||||
fieldOptions: {
|
||||
reduceOptions: {
|
||||
calcs: [ReducerID.last],
|
||||
},
|
||||
});
|
||||
@ -52,7 +52,7 @@ describe('FieldDisplay', () => {
|
||||
|
||||
it('show all numeric values', () => {
|
||||
const options = createDisplayOptions({
|
||||
fieldOptions: {
|
||||
reduceOptions: {
|
||||
values: true, //
|
||||
limit: 1000,
|
||||
calcs: [],
|
||||
@ -64,7 +64,7 @@ describe('FieldDisplay', () => {
|
||||
|
||||
it('show 2 numeric values (limit)', () => {
|
||||
const options = createDisplayOptions({
|
||||
fieldOptions: {
|
||||
reduceOptions: {
|
||||
values: true, //
|
||||
limit: 2,
|
||||
calcs: [],
|
||||
@ -173,12 +173,8 @@ describe('FieldDisplay', () => {
|
||||
},
|
||||
];
|
||||
const options = createDisplayOptions({
|
||||
fieldOptions: {
|
||||
reduceOptions: {
|
||||
calcs: [ReducerID.first],
|
||||
override: {},
|
||||
defaults: {
|
||||
mappings: mappingConfig,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@ -202,13 +198,9 @@ describe('FieldDisplay', () => {
|
||||
},
|
||||
];
|
||||
const options = createDisplayOptions({
|
||||
fieldOptions: {
|
||||
reduceOptions: {
|
||||
calcs: [ReducerID.first],
|
||||
values: true,
|
||||
override: {},
|
||||
defaults: {
|
||||
mappings: mappingConfig,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@ -253,7 +245,7 @@ function createDisplayOptions(extend: Partial<GetFieldDisplayValuesOptions> = {}
|
||||
replaceVariables: (value: string) => {
|
||||
return value;
|
||||
},
|
||||
fieldOptions: {
|
||||
reduceOptions: {
|
||||
calcs: [],
|
||||
},
|
||||
fieldConfig: {
|
||||
|
@ -11,7 +11,6 @@ import {
|
||||
FieldConfigSource,
|
||||
FieldType,
|
||||
InterpolateFunction,
|
||||
ValueMapping,
|
||||
} from '../types';
|
||||
import { DataFrameView } from '../dataframe/DataFrameView';
|
||||
import { GraphSeriesValue } from '../types/graph';
|
||||
@ -20,15 +19,16 @@ import { reduceField, ReducerID } from '../transformations/fieldReducer';
|
||||
import { ScopedVars } from '../types/ScopedVars';
|
||||
import { getTimeField } from '../dataframe/processDataFrame';
|
||||
|
||||
// export interface FieldDisplayOptions extends FieldConfigSource {
|
||||
export interface FieldDisplayOptions {
|
||||
values?: boolean; // If true show each row value
|
||||
limit?: number; // if showing all values limit
|
||||
calcs: string[]; // when !values, pick one value for the whole field
|
||||
override?: any;
|
||||
defaults?: {
|
||||
mappings: ValueMapping[];
|
||||
};
|
||||
/**
|
||||
* Options for how to turn DataFrames into an array of display values
|
||||
*/
|
||||
export interface ReduceDataOptions {
|
||||
/* If true show each row value */
|
||||
values?: boolean;
|
||||
/** if showing all values limit */
|
||||
limit?: number;
|
||||
/** When !values, pick one value for the whole field */
|
||||
calcs: string[];
|
||||
}
|
||||
|
||||
// TODO: use built in variables, same as for data links?
|
||||
@ -81,7 +81,7 @@ export interface FieldDisplay {
|
||||
|
||||
export interface GetFieldDisplayValuesOptions {
|
||||
data?: DataFrame[];
|
||||
fieldOptions: FieldDisplayOptions;
|
||||
reduceOptions: ReduceDataOptions;
|
||||
fieldConfig: FieldConfigSource;
|
||||
replaceVariables: InterpolateFunction;
|
||||
sparkline?: boolean; // Calculate the sparkline
|
||||
@ -92,8 +92,8 @@ export interface GetFieldDisplayValuesOptions {
|
||||
export const DEFAULT_FIELD_DISPLAY_VALUES_LIMIT = 25;
|
||||
|
||||
export const getFieldDisplayValues = (options: GetFieldDisplayValuesOptions): FieldDisplay[] => {
|
||||
const { replaceVariables, fieldOptions, fieldConfig } = options;
|
||||
const calcs = fieldOptions.calcs.length ? fieldOptions.calcs : [ReducerID.last];
|
||||
const { replaceVariables, reduceOptions, fieldConfig } = options;
|
||||
const calcs = reduceOptions.calcs.length ? reduceOptions.calcs : [ReducerID.last];
|
||||
|
||||
const values: FieldDisplay[] = [];
|
||||
|
||||
@ -101,7 +101,7 @@ export const getFieldDisplayValues = (options: GetFieldDisplayValuesOptions): Fi
|
||||
// Field overrides are applied already
|
||||
const data = options.data;
|
||||
let hitLimit = false;
|
||||
const limit = fieldOptions.limit ? fieldOptions.limit : DEFAULT_FIELD_DISPLAY_VALUES_LIMIT;
|
||||
const limit = reduceOptions.limit ? reduceOptions.limit : DEFAULT_FIELD_DISPLAY_VALUES_LIMIT;
|
||||
const defaultTitle = getTitleTemplate(fieldConfig.defaults.title, calcs, data);
|
||||
const scopedVars: ScopedVars = {};
|
||||
|
||||
@ -129,7 +129,7 @@ export const getFieldDisplayValues = (options: GetFieldDisplayValuesOptions): Fi
|
||||
|
||||
const title = config.title ? config.title : defaultTitle;
|
||||
// Show all rows
|
||||
if (fieldOptions.values) {
|
||||
if (reduceOptions.values) {
|
||||
const usesCellValues = title.indexOf(VAR_CELL_PREFIX) >= 0;
|
||||
|
||||
for (let j = 0; j < field.values.length; j++) {
|
||||
|
@ -13,8 +13,8 @@ const createTheme = (theme: GrafanaTheme) => {
|
||||
colorSecondary: theme.colors.brandPrimary,
|
||||
|
||||
// UI
|
||||
appBg: theme.colors.bodyBg,
|
||||
appContentBg: theme.colors.bodyBg,
|
||||
appBg: theme.colors.pageBg,
|
||||
appContentBg: theme.colors.pageBg,
|
||||
appBorderColor: theme.colors.pageHeaderBorder,
|
||||
appBorderRadius: 4,
|
||||
|
||||
@ -29,7 +29,7 @@ const createTheme = (theme: GrafanaTheme) => {
|
||||
// Toolbar default and active colors
|
||||
barTextColor: theme.colors.formInputBorderActive,
|
||||
barSelectedColor: theme.colors.brandPrimary,
|
||||
barBg: theme.colors.bodyBg,
|
||||
barBg: theme.colors.pageBg,
|
||||
|
||||
// Form colors
|
||||
inputBg: theme.colors.formInputBg,
|
||||
|
@ -5,6 +5,7 @@ import { css, cx } from 'emotion';
|
||||
import { getFocusCss, getPropertiesForButtonSize } from '../commonStyles';
|
||||
|
||||
export type RadioButtonSize = 'sm' | 'md';
|
||||
|
||||
export interface RadioButtonProps {
|
||||
size?: RadioButtonSize;
|
||||
disabled?: boolean;
|
||||
@ -12,9 +13,10 @@ export interface RadioButtonProps {
|
||||
active: boolean;
|
||||
id: string;
|
||||
onChange: () => void;
|
||||
fullWidth?: boolean;
|
||||
}
|
||||
|
||||
const getRadioButtonStyles = stylesFactory((theme: GrafanaTheme, size: RadioButtonSize) => {
|
||||
const getRadioButtonStyles = stylesFactory((theme: GrafanaTheme, size: RadioButtonSize, fullWidth?: boolean) => {
|
||||
const { fontSize, height } = getPropertiesForButtonSize(theme, size);
|
||||
const horizontalPadding = theme.spacing[size] ?? theme.spacing.md;
|
||||
const c = theme.colors;
|
||||
@ -79,6 +81,8 @@ const getRadioButtonStyles = stylesFactory((theme: GrafanaTheme, size: RadioButt
|
||||
background: ${bg};
|
||||
cursor: pointer;
|
||||
z-index: 1;
|
||||
flex-grow: ${fullWidth ? 1 : 0};
|
||||
text-align: center;
|
||||
|
||||
user-select: none;
|
||||
|
||||
@ -99,9 +103,10 @@ export const RadioButton: React.FC<RadioButtonProps> = ({
|
||||
onChange,
|
||||
id,
|
||||
name = undefined,
|
||||
fullWidth,
|
||||
}) => {
|
||||
const theme = useTheme();
|
||||
const styles = getRadioButtonStyles(theme, size);
|
||||
const styles = getRadioButtonStyles(theme, size, fullWidth);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -17,7 +17,7 @@ export default {
|
||||
const sizes: RadioButtonSize[] = ['sm', 'md'];
|
||||
|
||||
export const simple = () => {
|
||||
const [selected, setSelected] = useState();
|
||||
const [selected, setSelected] = useState('graphite');
|
||||
const BEHAVIOUR_GROUP = 'Behaviour props';
|
||||
const disabled = boolean('Disabled', false, BEHAVIOUR_GROUP);
|
||||
const disabledItem = select('Disabled item', ['', 'graphite', 'prometheus', 'elastic'], '', BEHAVIOUR_GROUP);
|
||||
@ -36,8 +36,37 @@ export const simple = () => {
|
||||
disabled={disabled}
|
||||
disabledOptions={[disabledItem]}
|
||||
value={selected}
|
||||
onChange={setSelected}
|
||||
onChange={v => setSelected(v!)}
|
||||
size={size}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export const fullWidth = () => {
|
||||
const [selected, setSelected] = useState('elastic');
|
||||
const BEHAVIOUR_GROUP = 'Behaviour props';
|
||||
const disabled = boolean('Disabled', false, BEHAVIOUR_GROUP);
|
||||
const disabledItem = select('Disabled item', ['', 'graphite', 'prometheus', 'elastic'], '', BEHAVIOUR_GROUP);
|
||||
const VISUAL_GROUP = 'Visual options';
|
||||
const size = select<RadioButtonSize>('Size', sizes, 'md', VISUAL_GROUP);
|
||||
|
||||
const options = [
|
||||
{ label: 'Prometheus', value: 'prometheus' },
|
||||
{ label: 'Graphite', value: 'graphite' },
|
||||
{ label: 'Elastic', value: 'elastic' },
|
||||
];
|
||||
|
||||
return (
|
||||
<div style={{ width: '100%' }}>
|
||||
<RadioButtonGroup
|
||||
options={options}
|
||||
disabled={disabled}
|
||||
disabledOptions={[disabledItem]}
|
||||
value={selected}
|
||||
onChange={v => setSelected(v!)}
|
||||
size={size}
|
||||
fullWidth
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
@ -39,6 +39,7 @@ interface RadioButtonGroupProps<T> {
|
||||
options: Array<SelectableValue<T>>;
|
||||
onChange?: (value?: T) => void;
|
||||
size?: RadioButtonSize;
|
||||
fullWidth?: boolean;
|
||||
}
|
||||
|
||||
export function RadioButtonGroup<T>({
|
||||
@ -48,6 +49,7 @@ export function RadioButtonGroup<T>({
|
||||
disabled,
|
||||
disabledOptions,
|
||||
size = 'md',
|
||||
fullWidth,
|
||||
}: RadioButtonGroupProps<T>) {
|
||||
const handleOnChange = useCallback(
|
||||
(option: SelectableValue<T>) => {
|
||||
@ -75,6 +77,7 @@ export function RadioButtonGroup<T>({
|
||||
onChange={handleOnChange(o)}
|
||||
id={`option-${o.value}`}
|
||||
name={groupName.current}
|
||||
fullWidth
|
||||
>
|
||||
{o.label}
|
||||
</RadioButton>
|
||||
|
7
packages/grafana-ui/src/components/OptionsUI/stats.tsx
Normal file
7
packages/grafana-ui/src/components/OptionsUI/stats.tsx
Normal file
@ -0,0 +1,7 @@
|
||||
import React from 'react';
|
||||
import { FieldConfigEditorProps, ReducerID } from '@grafana/data';
|
||||
import { StatsPicker } from '../StatsPicker/StatsPicker';
|
||||
|
||||
export const StatsPickerEditor: React.FC<FieldConfigEditorProps<string[], any>> = ({ value, onChange }) => {
|
||||
return <StatsPicker stats={value} onChange={onChange} allowMultiple={false} defaultStat={ReducerID.mean} />;
|
||||
};
|
@ -9,7 +9,7 @@ import { StatsPicker } from '../StatsPicker/StatsPicker';
|
||||
// Types
|
||||
import Select from '../Select/Select';
|
||||
import {
|
||||
FieldDisplayOptions,
|
||||
ReduceDataOptions,
|
||||
DEFAULT_FIELD_DISPLAY_VALUES_LIMIT,
|
||||
ReducerID,
|
||||
toNumberString,
|
||||
@ -32,8 +32,8 @@ const showOptions: Array<SelectableValue<boolean>> = [
|
||||
|
||||
export interface Props {
|
||||
labelWidth?: number;
|
||||
value: FieldDisplayOptions;
|
||||
onChange: (value: FieldDisplayOptions, event?: React.SyntheticEvent<HTMLElement>) => void;
|
||||
value: ReduceDataOptions;
|
||||
onChange: (value: ReduceDataOptions, event?: React.SyntheticEvent<HTMLElement>) => void;
|
||||
}
|
||||
|
||||
export class FieldDisplayEditor extends PureComponent<Props> {
|
||||
|
@ -11,7 +11,7 @@ import {
|
||||
MappingType,
|
||||
VizOrientation,
|
||||
PanelModel,
|
||||
FieldDisplayOptions,
|
||||
ReduceDataOptions,
|
||||
ThresholdsMode,
|
||||
ThresholdsConfig,
|
||||
validateFieldConfig,
|
||||
@ -19,11 +19,11 @@ import {
|
||||
} from '@grafana/data';
|
||||
|
||||
export interface SingleStatBaseOptions {
|
||||
fieldOptions: FieldDisplayOptions;
|
||||
reduceOptions: ReduceDataOptions;
|
||||
orientation: VizOrientation;
|
||||
}
|
||||
|
||||
const optionsToKeep = ['fieldOptions', 'orientation'];
|
||||
const optionsToKeep = ['reduceOptions', 'orientation'];
|
||||
|
||||
export function sharedSingleStatPanelChangedHandler(
|
||||
panel: PanelModel<Partial<SingleStatBaseOptions>> | any,
|
||||
@ -131,9 +131,9 @@ export function sharedSingleStatMigrationHandler(panel: PanelModel<SingleStatBas
|
||||
options = moveThresholdsAndMappingsToField(options);
|
||||
}
|
||||
|
||||
if (previousVersion < 6.6) {
|
||||
const { fieldOptions } = options;
|
||||
const { fieldOptions } = options;
|
||||
|
||||
if (previousVersion < 6.6) {
|
||||
// discard the old `override` options and enter an empty array
|
||||
if (fieldOptions && fieldOptions.override) {
|
||||
const { override, ...rest } = options.fieldOptions;
|
||||
@ -178,16 +178,24 @@ export function sharedSingleStatMigrationHandler(panel: PanelModel<SingleStatBas
|
||||
panel.fieldConfig = panel.fieldConfig || { defaults: {}, overrides: [] };
|
||||
panel.fieldConfig = {
|
||||
defaults:
|
||||
options.fieldOptions && options.fieldOptions.defaults
|
||||
? { ...panel.fieldConfig.defaults, ...options.fieldOptions.defaults }
|
||||
fieldOptions && fieldOptions.defaults
|
||||
? { ...panel.fieldConfig.defaults, ...fieldOptions.defaults }
|
||||
: panel.fieldConfig.defaults,
|
||||
overrides:
|
||||
options.fieldOptions && options.fieldOptions.overrides
|
||||
? [...panel.fieldConfig.overrides, ...options.fieldOptions.overrides]
|
||||
fieldOptions && fieldOptions.overrides
|
||||
? [...panel.fieldConfig.overrides, ...fieldOptions.overrides]
|
||||
: panel.fieldConfig.overrides,
|
||||
};
|
||||
delete options.fieldOptions.defaults;
|
||||
delete options.fieldOptions.overrides;
|
||||
|
||||
if (fieldOptions) {
|
||||
options.reduceOptions = {
|
||||
values: fieldOptions.values,
|
||||
limit: fieldOptions.limit,
|
||||
calcs: fieldOptions.calcs,
|
||||
};
|
||||
}
|
||||
|
||||
delete options.fieldOptions;
|
||||
}
|
||||
|
||||
return options as SingleStatBaseOptions;
|
||||
|
@ -3,7 +3,7 @@ import React, { PureComponent } from 'react';
|
||||
import isArray from 'lodash/isArray';
|
||||
import difference from 'lodash/difference';
|
||||
|
||||
import { Select } from '../Select/Select';
|
||||
import { Select } from '../Forms/Select/Select';
|
||||
|
||||
import { fieldReducers, SelectableValue } from '@grafana/data';
|
||||
|
||||
@ -11,7 +11,6 @@ interface Props {
|
||||
placeholder?: string;
|
||||
onChange: (stats: string[]) => void;
|
||||
stats: string[];
|
||||
width?: number;
|
||||
allowMultiple?: boolean;
|
||||
defaultStat?: string;
|
||||
}
|
||||
@ -63,12 +62,11 @@ export class StatsPicker extends PureComponent<Props> {
|
||||
};
|
||||
|
||||
render() {
|
||||
const { width, stats, allowMultiple, defaultStat, placeholder } = this.props;
|
||||
const { stats, allowMultiple, defaultStat, placeholder } = this.props;
|
||||
|
||||
const select = fieldReducers.selectOptions(stats);
|
||||
return (
|
||||
<Select
|
||||
width={width}
|
||||
value={select.current}
|
||||
isClearable={!defaultStat}
|
||||
isMulti={allowMultiple}
|
||||
|
@ -24,6 +24,7 @@ import { ThresholdsValueEditor } from '../components/OptionsUI/thresholds';
|
||||
import { UnitValueEditor } from '../components/OptionsUI/units';
|
||||
import { DataLinksValueEditor } from '../components/OptionsUI/links';
|
||||
import { ColorValueEditor } from '../components/OptionsUI/color';
|
||||
import { StatsPickerEditor } from '../components/OptionsUI/stats';
|
||||
|
||||
/**
|
||||
* Returns collection of common field config properties definitions
|
||||
@ -227,7 +228,7 @@ export const getStandardOptionEditors = () => {
|
||||
id: 'radio',
|
||||
name: 'Radio',
|
||||
description: 'Allows option selection',
|
||||
editor: props => <Forms.RadioButtonGroup {...props} options={props.item.settings?.options} />,
|
||||
editor: props => <Forms.RadioButtonGroup {...props} options={props.item.settings?.options} fullWidth />,
|
||||
};
|
||||
|
||||
const unit: StandardEditorsRegistryItem<string> = {
|
||||
@ -265,5 +266,12 @@ export const getStandardOptionEditors = () => {
|
||||
editor: DataLinksValueEditor as any,
|
||||
};
|
||||
|
||||
return [text, number, boolean, radio, select, unit, mappings, thresholds, links, color];
|
||||
const statsPicker: StandardEditorsRegistryItem<string[]> = {
|
||||
id: 'stats-picker',
|
||||
name: 'Stats Picker',
|
||||
editor: StatsPickerEditor as any,
|
||||
description: '',
|
||||
};
|
||||
|
||||
return [text, number, boolean, radio, select, unit, mappings, thresholds, links, color, statsPicker];
|
||||
};
|
||||
|
@ -65,10 +65,10 @@ export const OptionsPaneContent: React.FC<{
|
||||
|
||||
const renderCustomPanelSettings = useCallback(
|
||||
(plugin: PanelPlugin) => {
|
||||
const editors = [];
|
||||
const editors: JSX.Element[] = [];
|
||||
if (plugin.editor && panel) {
|
||||
editors.push(
|
||||
<div className={styles.legacyOptions}>
|
||||
<div className={styles.legacyOptions} key="plugin custom panel settings">
|
||||
<plugin.editor
|
||||
data={data}
|
||||
options={panel.getOptions()}
|
||||
@ -83,12 +83,17 @@ export const OptionsPaneContent: React.FC<{
|
||||
// When editor created declaratively
|
||||
if (plugin.optionEditors && panel) {
|
||||
editors.push(
|
||||
<PanelOptionsEditor options={panel.getOptions()} onChange={onPanelOptionsChanged} plugin={plugin} />
|
||||
<PanelOptionsEditor
|
||||
key="panel options"
|
||||
options={panel.getOptions()}
|
||||
onChange={onPanelOptionsChanged}
|
||||
plugin={plugin}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (editors.length > 0) {
|
||||
return <>{editors}</>;
|
||||
return editors;
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -228,7 +228,7 @@ export class PanelEditorUnconnected extends PureComponent<Props> {
|
||||
const { plugin, dashboard, data, panel } = this.props;
|
||||
|
||||
if (!plugin) {
|
||||
return null;
|
||||
return <div />;
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -1,4 +1,5 @@
|
||||
import React, { useMemo } from 'react';
|
||||
import { set as lodashSet, get as lodashGet } from 'lodash';
|
||||
import { PanelPlugin } from '@grafana/data';
|
||||
import { Forms } from '@grafana/ui';
|
||||
|
||||
@ -12,18 +13,16 @@ export const PanelOptionsEditor: React.FC<PanelOptionsEditorProps<any>> = ({ plu
|
||||
const optionEditors = useMemo(() => plugin.optionEditors, [plugin]);
|
||||
|
||||
const onOptionChange = (key: string, value: any) => {
|
||||
onChange({
|
||||
...options,
|
||||
[key]: value,
|
||||
});
|
||||
const newOptions = lodashSet({ ...options }, key, value);
|
||||
onChange(newOptions);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{optionEditors.list().map(e => {
|
||||
return (
|
||||
<Forms.Field label={e.name} description={e.description}>
|
||||
<e.editor value={options[e.id]} onChange={value => onOptionChange(e.id, value)} item={e} />
|
||||
<Forms.Field label={e.name} description={e.description} key={e.id}>
|
||||
<e.editor value={lodashGet(options, e.id)} onChange={value => onOptionChange(e.id, value)} item={e} />
|
||||
</Forms.Field>
|
||||
);
|
||||
})}
|
||||
|
@ -45,7 +45,9 @@ describe('BarGauge Panel Migrations', () => {
|
||||
type: 'bargauge',
|
||||
} as Omit<PanelModel, 'fieldConfig'>;
|
||||
|
||||
expect(barGaugePanelMigrationHandler(panel as PanelModel)).toMatchSnapshot();
|
||||
const newOptions = barGaugePanelMigrationHandler(panel as PanelModel);
|
||||
|
||||
// should mutate panel model and move field config out of panel.options
|
||||
expect((panel as any).fieldConfig).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"defaults": Object {
|
||||
@ -81,5 +83,20 @@ describe('BarGauge Panel Migrations', () => {
|
||||
"overrides": Array [],
|
||||
}
|
||||
`);
|
||||
|
||||
// should options options
|
||||
expect(newOptions).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"displayMode": "lcd",
|
||||
"orientation": "vertical",
|
||||
"reduceOptions": Object {
|
||||
"calcs": Array [
|
||||
"mean",
|
||||
],
|
||||
"limit": undefined,
|
||||
"values": false,
|
||||
},
|
||||
}
|
||||
`);
|
||||
});
|
||||
});
|
||||
|
@ -65,7 +65,7 @@ function createBarGaugePanelWithData(data: PanelData): ReactWrapper<PanelProps<B
|
||||
|
||||
const options: BarGaugeOptions = {
|
||||
displayMode: BarGaugeDisplayMode.Lcd,
|
||||
fieldOptions: {
|
||||
reduceOptions: {
|
||||
calcs: ['mean'],
|
||||
values: false,
|
||||
},
|
||||
|
@ -50,7 +50,7 @@ export class BarGaugePanel extends PureComponent<PanelProps<BarGaugeOptions>> {
|
||||
const { data, options, replaceVariables, fieldConfig } = this.props;
|
||||
return getFieldDisplayValues({
|
||||
fieldConfig,
|
||||
fieldOptions: options.fieldOptions,
|
||||
reduceOptions: options.reduceOptions,
|
||||
replaceVariables,
|
||||
theme: config.theme,
|
||||
data: data.series,
|
||||
|
@ -16,7 +16,7 @@ import {
|
||||
import {
|
||||
DataLink,
|
||||
FieldConfig,
|
||||
FieldDisplayOptions,
|
||||
ReduceDataOptions,
|
||||
PanelEditorProps,
|
||||
ThresholdsConfig,
|
||||
ValueMapping,
|
||||
@ -30,10 +30,10 @@ import {
|
||||
import { NewPanelEditorContext } from '../../../features/dashboard/components/PanelEditor/PanelEditor';
|
||||
|
||||
export class BarGaugePanelEditor extends PureComponent<PanelEditorProps<BarGaugeOptions>> {
|
||||
onDisplayOptionsChanged = (fieldOptions: FieldDisplayOptions) =>
|
||||
onDisplayOptionsChanged = (fieldOptions: ReduceDataOptions) =>
|
||||
this.props.onOptionsChange({
|
||||
...this.props.options,
|
||||
fieldOptions,
|
||||
reduceOptions: fieldOptions,
|
||||
});
|
||||
|
||||
onOrientationChange = ({ value }: any) => this.props.onOptionsChange({ ...this.props.options, orientation: value });
|
||||
@ -84,7 +84,7 @@ export class BarGaugePanelEditor extends PureComponent<PanelEditorProps<BarGauge
|
||||
|
||||
render() {
|
||||
const { options, fieldConfig } = this.props;
|
||||
const { fieldOptions } = options;
|
||||
const { reduceOptions: fieldOptions } = options;
|
||||
const { defaults } = fieldConfig;
|
||||
|
||||
const labelWidth = 6;
|
||||
|
@ -1,31 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`BarGauge Panel Migrations from 6.2 1`] = `
|
||||
Object {
|
||||
"displayMode": "lcd",
|
||||
"fieldOptions": Object {
|
||||
"calcs": Array [
|
||||
"mean",
|
||||
],
|
||||
"thresholds": Array [
|
||||
Object {
|
||||
"color": "green",
|
||||
"index": 0,
|
||||
"value": -Infinity,
|
||||
},
|
||||
Object {
|
||||
"color": "orange",
|
||||
"index": 1,
|
||||
"value": 40,
|
||||
},
|
||||
Object {
|
||||
"color": "red",
|
||||
"index": 2,
|
||||
"value": 80,
|
||||
},
|
||||
],
|
||||
"values": false,
|
||||
},
|
||||
"orientation": "vertical",
|
||||
}
|
||||
`;
|
@ -2,7 +2,7 @@ import { sharedSingleStatPanelChangedHandler } from '@grafana/ui';
|
||||
import { PanelPlugin } from '@grafana/data';
|
||||
import { BarGaugePanel } from './BarGaugePanel';
|
||||
import { BarGaugeOptions, defaults } from './types';
|
||||
import { standardFieldConfig } from '../stat/types';
|
||||
import { standardFieldConfig, addStandardDataReduceOptions } from '../stat/types';
|
||||
import { BarGaugePanelEditor } from './BarGaugePanelEditor';
|
||||
import { barGaugePanelMigrationHandler } from './BarGaugeMigrations';
|
||||
|
||||
@ -11,20 +11,26 @@ export const plugin = new PanelPlugin<BarGaugeOptions>(BarGaugePanel)
|
||||
.setEditor(BarGaugePanelEditor)
|
||||
.setFieldConfigDefaults(standardFieldConfig)
|
||||
.setPanelOptions(builder => {
|
||||
/* addStandardSingleValueOptions(builder); */
|
||||
addStandardDataReduceOptions(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' },
|
||||
],
|
||||
},
|
||||
});
|
||||
builder
|
||||
.addRadio({
|
||||
id: 'displayMode',
|
||||
name: 'Display mode',
|
||||
description: 'Controls the bar style',
|
||||
settings: {
|
||||
options: [
|
||||
{ value: 'basic', label: 'Basic' },
|
||||
{ value: 'gradient', label: 'Gradient' },
|
||||
{ value: 'lcd', label: 'Retro LCD' },
|
||||
],
|
||||
},
|
||||
})
|
||||
.addBooleanSwitch({
|
||||
id: 'showUnfilled',
|
||||
name: 'Show unfilled area',
|
||||
description: 'When enabled renders the unfilled region as gray',
|
||||
});
|
||||
})
|
||||
.setPanelChangeHandler(sharedSingleStatPanelChangedHandler)
|
||||
.setMigrationHandler(barGaugePanelMigrationHandler);
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { SingleStatBaseOptions, BarGaugeDisplayMode } from '@grafana/ui';
|
||||
import { standardGaugeFieldOptions } from '../gauge/types';
|
||||
import { commonValueOptionDefaults } from '../stat/types';
|
||||
import { VizOrientation, SelectableValue } from '@grafana/data';
|
||||
|
||||
export interface BarGaugeOptions extends SingleStatBaseOptions {
|
||||
@ -16,6 +16,6 @@ export const displayModes: Array<SelectableValue<string>> = [
|
||||
export const defaults: BarGaugeOptions = {
|
||||
displayMode: BarGaugeDisplayMode.Lcd,
|
||||
orientation: VizOrientation.Horizontal,
|
||||
fieldOptions: standardGaugeFieldOptions,
|
||||
reduceOptions: commonValueOptionDefaults,
|
||||
showUnfilled: true,
|
||||
};
|
||||
|
@ -82,10 +82,10 @@ describe('Gauge Panel Migrations', () => {
|
||||
|
||||
// Ignored due to the API change
|
||||
//@ts-ignore
|
||||
expect(result.fieldOptions.defaults).toBeUndefined();
|
||||
expect(result.reduceOptions.defaults).toBeUndefined();
|
||||
// Ignored due to the API change
|
||||
//@ts-ignore
|
||||
expect(result.fieldOptions.overrides).toBeUndefined();
|
||||
expect(result.reduceOptions.overrides).toBeUndefined();
|
||||
|
||||
expect((panel as PanelModel).fieldConfig).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
|
@ -43,7 +43,7 @@ export class GaugePanel extends PureComponent<PanelProps<GaugeOptions>> {
|
||||
const { data, options, replaceVariables, fieldConfig } = this.props;
|
||||
return getFieldDisplayValues({
|
||||
fieldConfig,
|
||||
fieldOptions: options.fieldOptions,
|
||||
reduceOptions: options.reduceOptions,
|
||||
replaceVariables,
|
||||
theme: config.theme,
|
||||
data: data.series,
|
||||
|
@ -12,7 +12,7 @@ import {
|
||||
} from '@grafana/ui';
|
||||
import {
|
||||
PanelEditorProps,
|
||||
FieldDisplayOptions,
|
||||
ReduceDataOptions,
|
||||
ThresholdsConfig,
|
||||
DataLink,
|
||||
FieldConfig,
|
||||
@ -39,14 +39,14 @@ export class GaugePanelEditor extends PureComponent<PanelEditorProps<GaugeOption
|
||||
});
|
||||
|
||||
onDisplayOptionsChanged = (
|
||||
fieldOptions: FieldDisplayOptions,
|
||||
fieldOptions: ReduceDataOptions,
|
||||
event?: React.SyntheticEvent<HTMLElement>,
|
||||
callback?: () => void
|
||||
) => {
|
||||
this.props.onOptionsChange(
|
||||
{
|
||||
...this.props.options,
|
||||
fieldOptions,
|
||||
reduceOptions: fieldOptions,
|
||||
},
|
||||
callback
|
||||
);
|
||||
@ -94,24 +94,28 @@ export class GaugePanelEditor extends PureComponent<PanelEditorProps<GaugeOption
|
||||
|
||||
render() {
|
||||
const { options, fieldConfig } = this.props;
|
||||
const { showThresholdLabels, showThresholdMarkers, fieldOptions } = options;
|
||||
const { showThresholdLabels, showThresholdMarkers, reduceOptions: valueOptions } = options;
|
||||
|
||||
const { defaults } = fieldConfig;
|
||||
|
||||
const suggestions = fieldOptions.values
|
||||
const suggestions = valueOptions.values
|
||||
? getDataLinksVariableSuggestions(this.props.data.series)
|
||||
: getCalculationValueDataLinksVariableSuggestions(this.props.data.series);
|
||||
|
||||
return (
|
||||
<NewPanelEditorContext.Consumer>
|
||||
{useNewEditor => {
|
||||
if (useNewEditor) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<PanelOptionsGrid>
|
||||
<PanelOptionsGroup title="Display">
|
||||
<FieldDisplayEditor
|
||||
onChange={this.onDisplayOptionsChanged}
|
||||
value={fieldOptions}
|
||||
value={valueOptions}
|
||||
labelWidth={this.labelWidth}
|
||||
/>
|
||||
<Switch
|
||||
@ -128,36 +132,27 @@ export class GaugePanelEditor extends PureComponent<PanelEditorProps<GaugeOption
|
||||
/>
|
||||
</PanelOptionsGroup>
|
||||
|
||||
<>
|
||||
{!useNewEditor && (
|
||||
<>
|
||||
<PanelOptionsGroup title="Field">
|
||||
<FieldPropertiesEditor
|
||||
showMinMax={true}
|
||||
showTitle={true}
|
||||
onChange={this.onDefaultsChange}
|
||||
value={defaults}
|
||||
/>
|
||||
</PanelOptionsGroup>
|
||||
<PanelOptionsGroup title="Field">
|
||||
<FieldPropertiesEditor
|
||||
showMinMax={true}
|
||||
showTitle={true}
|
||||
onChange={this.onDefaultsChange}
|
||||
value={defaults}
|
||||
/>
|
||||
</PanelOptionsGroup>
|
||||
|
||||
<ThresholdsEditor onChange={this.onThresholdsChanged} thresholds={defaults.thresholds} />
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
<ThresholdsEditor onChange={this.onThresholdsChanged} thresholds={defaults.thresholds} />
|
||||
</PanelOptionsGrid>
|
||||
{!useNewEditor && (
|
||||
<>
|
||||
<LegacyValueMappingsEditor onChange={this.onValueMappingsChanged} valueMappings={defaults.mappings} />
|
||||
<PanelOptionsGroup title="Data links">
|
||||
<DataLinksEditor
|
||||
value={defaults.links}
|
||||
onChange={this.onDataLinksChanged}
|
||||
suggestions={suggestions}
|
||||
maxLinks={10}
|
||||
/>
|
||||
</PanelOptionsGroup>
|
||||
</>
|
||||
)}
|
||||
|
||||
<LegacyValueMappingsEditor onChange={this.onValueMappingsChanged} valueMappings={defaults.mappings} />
|
||||
<PanelOptionsGroup title="Data links">
|
||||
<DataLinksEditor
|
||||
value={defaults.links}
|
||||
onChange={this.onDataLinksChanged}
|
||||
suggestions={suggestions}
|
||||
maxLinks={10}
|
||||
/>
|
||||
</PanelOptionsGroup>
|
||||
</>
|
||||
);
|
||||
}}
|
||||
|
@ -2,12 +2,14 @@
|
||||
|
||||
exports[`Gauge Panel Migrations from 6.1.1 1`] = `
|
||||
Object {
|
||||
"fieldOptions": Object {
|
||||
"orientation": "auto",
|
||||
"reduceOptions": Object {
|
||||
"calcs": Array [
|
||||
"last",
|
||||
],
|
||||
"limit": undefined,
|
||||
"values": undefined,
|
||||
},
|
||||
"orientation": "auto",
|
||||
"showThresholdLabels": true,
|
||||
"showThresholdMarkers": true,
|
||||
}
|
||||
|
@ -2,12 +2,27 @@ import { PanelPlugin } from '@grafana/data';
|
||||
import { GaugePanelEditor } from './GaugePanelEditor';
|
||||
import { GaugePanel } from './GaugePanel';
|
||||
import { GaugeOptions, defaults } from './types';
|
||||
import { standardFieldConfig } from '../stat/types';
|
||||
import { standardFieldConfig, addStandardDataReduceOptions } from '../stat/types';
|
||||
import { gaugePanelMigrationHandler, gaugePanelChangedHandler } from './GaugeMigrations';
|
||||
|
||||
export const plugin = new PanelPlugin<GaugeOptions>(GaugePanel)
|
||||
.setDefaults(defaults)
|
||||
.setFieldConfigDefaults(standardFieldConfig)
|
||||
.setEditor(GaugePanelEditor)
|
||||
.setPanelOptions(builder => {
|
||||
addStandardDataReduceOptions(builder);
|
||||
|
||||
builder
|
||||
.addBooleanSwitch({
|
||||
id: 'showThresholdLabels',
|
||||
name: 'Show threshold Labels',
|
||||
description: 'Render the threshold values around the gauge bar',
|
||||
})
|
||||
.addBooleanSwitch({
|
||||
id: 'showThresholdMarkers',
|
||||
name: 'Show threshold markers',
|
||||
description: 'Renders the thresholds as an outer bar',
|
||||
});
|
||||
})
|
||||
.setPanelChangeHandler(gaugePanelChangedHandler)
|
||||
.setMigrationHandler(gaugePanelMigrationHandler);
|
||||
|
@ -1,16 +1,12 @@
|
||||
import { VizOrientation, FieldDisplayOptions, SelectableValue } from '@grafana/data';
|
||||
import { VizOrientation, SelectableValue } from '@grafana/data';
|
||||
import { SingleStatBaseOptions } from '@grafana/ui/src/components/SingleStatShared/SingleStatBaseOptions';
|
||||
import { standardFieldDisplayOptions } from '../stat/types';
|
||||
import { commonValueOptionDefaults } from '../stat/types';
|
||||
|
||||
export interface GaugeOptions extends SingleStatBaseOptions {
|
||||
showThresholdLabels: boolean;
|
||||
showThresholdMarkers: boolean;
|
||||
}
|
||||
|
||||
export const standardGaugeFieldOptions: FieldDisplayOptions = {
|
||||
...standardFieldDisplayOptions,
|
||||
};
|
||||
|
||||
export const orientationOptions: Array<SelectableValue<VizOrientation>> = [
|
||||
{ value: VizOrientation.Auto, label: 'Auto' },
|
||||
{ value: VizOrientation.Horizontal, label: 'Horizontal' },
|
||||
@ -20,6 +16,6 @@ export const orientationOptions: Array<SelectableValue<VizOrientation>> = [
|
||||
export const defaults: GaugeOptions = {
|
||||
showThresholdMarkers: true,
|
||||
showThresholdLabels: false,
|
||||
fieldOptions: standardGaugeFieldOptions,
|
||||
reduceOptions: commonValueOptionDefaults,
|
||||
orientation: VizOrientation.Auto,
|
||||
};
|
||||
|
@ -1,9 +1,6 @@
|
||||
import { LegendOptions, GraphTooltipOptions } from '@grafana/ui';
|
||||
import { YAxis, FieldDisplayOptions } from '@grafana/data';
|
||||
|
||||
import { YAxis } from '@grafana/data';
|
||||
import { GraphLegendEditorLegendOptions } from './GraphLegendEditor';
|
||||
// TODO move out from single stat
|
||||
import { standardFieldDisplayOptions } from '../stat/types';
|
||||
|
||||
export interface SeriesOptions {
|
||||
color?: string;
|
||||
@ -22,7 +19,6 @@ export interface Options {
|
||||
series: {
|
||||
[alias: string]: SeriesOptions;
|
||||
};
|
||||
fieldOptions: FieldDisplayOptions;
|
||||
tooltipOptions: GraphTooltipOptions;
|
||||
}
|
||||
|
||||
@ -38,6 +34,5 @@ export const defaults: Options = {
|
||||
placement: 'under',
|
||||
},
|
||||
series: {},
|
||||
fieldOptions: { ...standardFieldDisplayOptions },
|
||||
tooltipOptions: { mode: 'single' },
|
||||
};
|
||||
|
@ -20,7 +20,7 @@ export class PieChartPanel extends PureComponent<Props> {
|
||||
|
||||
const values = getFieldDisplayValues({
|
||||
fieldConfig,
|
||||
fieldOptions: options.fieldOptions,
|
||||
reduceOptions: options.reduceOptions,
|
||||
data: data.series,
|
||||
theme: config.theme,
|
||||
replaceVariables: replaceVariables,
|
||||
|
@ -6,7 +6,7 @@ import {
|
||||
FieldPropertiesEditor,
|
||||
LegacyValueMappingsEditor,
|
||||
} from '@grafana/ui';
|
||||
import { PanelEditorProps, FieldDisplayOptions, ValueMapping, FieldConfig } from '@grafana/data';
|
||||
import { PanelEditorProps, ReduceDataOptions, ValueMapping, FieldConfig } from '@grafana/data';
|
||||
|
||||
import { PieChartOptionsBox } from './PieChartOptionsBox';
|
||||
import { PieChartOptions } from './types';
|
||||
@ -23,10 +23,10 @@ export class PieChartPanelEditor extends PureComponent<PanelEditorProps<PieChart
|
||||
});
|
||||
};
|
||||
|
||||
onDisplayOptionsChanged = (fieldOptions: FieldDisplayOptions) =>
|
||||
onDisplayOptionsChanged = (fieldOptions: ReduceDataOptions) =>
|
||||
this.props.onOptionsChange({
|
||||
...this.props.options,
|
||||
fieldOptions,
|
||||
reduceOptions: fieldOptions,
|
||||
});
|
||||
|
||||
onDefaultsChange = (field: FieldConfig) => {
|
||||
@ -38,7 +38,7 @@ export class PieChartPanelEditor extends PureComponent<PanelEditorProps<PieChart
|
||||
|
||||
render() {
|
||||
const { onOptionsChange, options, data, fieldConfig, onFieldConfigChange } = this.props;
|
||||
const { fieldOptions } = options;
|
||||
const { reduceOptions: fieldOptions } = options;
|
||||
const { defaults } = fieldConfig;
|
||||
|
||||
return (
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { PieChartType, SingleStatBaseOptions } from '@grafana/ui';
|
||||
import { standardFieldDisplayOptions } from '../stat/types';
|
||||
import { ReducerID, VizOrientation } from '@grafana/data';
|
||||
import { commonValueOptionDefaults } from '../stat/types';
|
||||
import { VizOrientation } from '@grafana/data';
|
||||
|
||||
export interface PieChartOptions extends SingleStatBaseOptions {
|
||||
pieType: PieChartType;
|
||||
@ -11,8 +11,5 @@ export const defaults: PieChartOptions = {
|
||||
pieType: PieChartType.PIE,
|
||||
strokeWidth: 1,
|
||||
orientation: VizOrientation.Auto,
|
||||
fieldOptions: {
|
||||
...standardFieldDisplayOptions,
|
||||
calcs: [ReducerID.last],
|
||||
},
|
||||
reduceOptions: commonValueOptionDefaults,
|
||||
};
|
||||
|
@ -42,7 +42,7 @@ export class StatPanel extends PureComponent<PanelProps<StatPanelOptions>> {
|
||||
yMax: value.field.max,
|
||||
};
|
||||
|
||||
const calc = options.fieldOptions.calcs[0];
|
||||
const calc = options.reduceOptions.calcs[0];
|
||||
if (calc === ReducerID.last) {
|
||||
sparkline.highlightIndex = sparkline.data.length - 1;
|
||||
}
|
||||
@ -76,7 +76,7 @@ export class StatPanel extends PureComponent<PanelProps<StatPanelOptions>> {
|
||||
|
||||
return getFieldDisplayValues({
|
||||
fieldConfig,
|
||||
fieldOptions: options.fieldOptions,
|
||||
reduceOptions: options.reduceOptions,
|
||||
replaceVariables,
|
||||
theme: config.theme,
|
||||
data: data.series,
|
||||
|
@ -15,7 +15,7 @@ import {
|
||||
|
||||
import {
|
||||
PanelEditorProps,
|
||||
FieldDisplayOptions,
|
||||
ReduceDataOptions,
|
||||
FieldConfig,
|
||||
ValueMapping,
|
||||
ThresholdsConfig,
|
||||
@ -53,10 +53,10 @@ export class StatPanelEditor extends PureComponent<PanelEditorProps<StatPanelOpt
|
||||
});
|
||||
};
|
||||
|
||||
onDisplayOptionsChanged = (fieldOptions: FieldDisplayOptions) =>
|
||||
onDisplayOptionsChanged = (fieldOptions: ReduceDataOptions) =>
|
||||
this.props.onOptionsChange({
|
||||
...this.props.options,
|
||||
fieldOptions,
|
||||
reduceOptions: fieldOptions,
|
||||
});
|
||||
|
||||
onColorModeChanged = ({ value }: any) => this.props.onOptionsChange({ ...this.props.options, colorMode: value });
|
||||
@ -84,21 +84,25 @@ export class StatPanelEditor extends PureComponent<PanelEditorProps<StatPanelOpt
|
||||
|
||||
render() {
|
||||
const { options, fieldConfig } = this.props;
|
||||
const { fieldOptions } = options;
|
||||
const { reduceOptions: valueOptions } = options;
|
||||
const { defaults } = fieldConfig;
|
||||
|
||||
const suggestions = fieldOptions.values
|
||||
const suggestions = valueOptions.values
|
||||
? getDataLinksVariableSuggestions(this.props.data.series)
|
||||
: getCalculationValueDataLinksVariableSuggestions(this.props.data.series);
|
||||
|
||||
return (
|
||||
<NewPanelEditorContext.Consumer>
|
||||
{useNewEditor => {
|
||||
if (useNewEditor) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<PanelOptionsGrid>
|
||||
<PanelOptionsGroup title="Display">
|
||||
<FieldDisplayEditor onChange={this.onDisplayOptionsChanged} value={fieldOptions} labelWidth={8} />
|
||||
<FieldDisplayEditor onChange={this.onDisplayOptionsChanged} value={valueOptions} labelWidth={8} />
|
||||
<div className="form-field">
|
||||
<FormLabel width={8}>Orientation</FormLabel>
|
||||
<Select
|
||||
@ -140,36 +144,28 @@ export class StatPanelEditor extends PureComponent<PanelEditorProps<StatPanelOpt
|
||||
/>
|
||||
</div>
|
||||
</PanelOptionsGroup>
|
||||
<>
|
||||
{!useNewEditor && (
|
||||
<>
|
||||
<PanelOptionsGroup title="Field">
|
||||
<FieldPropertiesEditor
|
||||
showMinMax={true}
|
||||
onChange={this.onDefaultsChange}
|
||||
value={defaults}
|
||||
showTitle={true}
|
||||
/>
|
||||
</PanelOptionsGroup>
|
||||
<ThresholdsEditor onChange={this.onThresholdsChanged} thresholds={defaults.thresholds} />
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
</PanelOptionsGrid>
|
||||
{!useNewEditor && (
|
||||
<>
|
||||
<LegacyValueMappingsEditor onChange={this.onValueMappingsChanged} valueMappings={defaults.mappings} />
|
||||
|
||||
<PanelOptionsGroup title="Data links">
|
||||
<DataLinksEditor
|
||||
value={defaults.links}
|
||||
onChange={this.onDataLinksChanged}
|
||||
suggestions={suggestions}
|
||||
maxLinks={10}
|
||||
/>
|
||||
</PanelOptionsGroup>
|
||||
</>
|
||||
)}
|
||||
<PanelOptionsGroup title="Field">
|
||||
<FieldPropertiesEditor
|
||||
showMinMax={true}
|
||||
onChange={this.onDefaultsChange}
|
||||
value={defaults}
|
||||
showTitle={true}
|
||||
/>
|
||||
</PanelOptionsGroup>
|
||||
<ThresholdsEditor onChange={this.onThresholdsChanged} thresholds={defaults.thresholds} />
|
||||
</PanelOptionsGrid>
|
||||
|
||||
<LegacyValueMappingsEditor onChange={this.onValueMappingsChanged} valueMappings={defaults.mappings} />
|
||||
|
||||
<PanelOptionsGroup title="Data links">
|
||||
<DataLinksEditor
|
||||
value={defaults.links}
|
||||
onChange={this.onDataLinksChanged}
|
||||
suggestions={suggestions}
|
||||
maxLinks={10}
|
||||
/>
|
||||
</PanelOptionsGroup>
|
||||
</>
|
||||
);
|
||||
}}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { sharedSingleStatMigrationHandler, sharedSingleStatPanelChangedHandler } from '@grafana/ui';
|
||||
import { PanelPlugin } from '@grafana/data';
|
||||
import { StatPanelOptions, defaults, standardFieldConfig } from './types';
|
||||
import { StatPanelOptions, defaults, standardFieldConfig, addStandardDataReduceOptions } from './types';
|
||||
import { StatPanel } from './StatPanel';
|
||||
import { StatPanelEditor } from './StatPanelEditor';
|
||||
|
||||
@ -8,6 +8,56 @@ export const plugin = new PanelPlugin<StatPanelOptions>(StatPanel)
|
||||
.setDefaults(defaults)
|
||||
.setFieldConfigDefaults(standardFieldConfig)
|
||||
.setEditor(StatPanelEditor)
|
||||
.setPanelOptions(builder => {
|
||||
addStandardDataReduceOptions(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' },
|
||||
],
|
||||
},
|
||||
})
|
||||
.addRadio({
|
||||
id: 'colorMode',
|
||||
name: 'Color mode',
|
||||
description: 'Color either the value or the background',
|
||||
settings: {
|
||||
options: [
|
||||
{ value: 'value', label: 'Value' },
|
||||
{ value: 'background', label: 'Background' },
|
||||
],
|
||||
},
|
||||
})
|
||||
.addRadio({
|
||||
id: 'graphMode',
|
||||
name: 'Graph mode',
|
||||
description: 'Stat panel graph / sparkline mode',
|
||||
settings: {
|
||||
options: [
|
||||
{ value: 'none', label: 'None' },
|
||||
{ value: 'area', label: 'Area' },
|
||||
],
|
||||
},
|
||||
})
|
||||
.addRadio({
|
||||
id: 'justifyMode',
|
||||
name: 'Justify mode',
|
||||
description: 'Value & title posititioning',
|
||||
settings: {
|
||||
options: [
|
||||
{ value: 'auto', label: 'Auto' },
|
||||
{ value: 'center', label: 'Center' },
|
||||
],
|
||||
},
|
||||
});
|
||||
})
|
||||
.setNoPadding()
|
||||
.setPanelChangeHandler(sharedSingleStatPanelChangedHandler)
|
||||
.setMigrationHandler(sharedSingleStatMigrationHandler);
|
||||
|
@ -2,10 +2,11 @@ import { SingleStatBaseOptions, BigValueColorMode, BigValueGraphMode, BigValueJu
|
||||
import {
|
||||
VizOrientation,
|
||||
ReducerID,
|
||||
FieldDisplayOptions,
|
||||
ReduceDataOptions,
|
||||
SelectableValue,
|
||||
FieldConfigSource,
|
||||
ThresholdsMode,
|
||||
standardEditorsRegistry,
|
||||
} from '@grafana/data';
|
||||
import { PanelOptionsEditorBuilder } from '@grafana/data/src/utils/OptionsUIBuilders';
|
||||
|
||||
@ -31,7 +32,7 @@ export const justifyModes: Array<SelectableValue<BigValueJustifyMode>> = [
|
||||
{ value: BigValueJustifyMode.Center, label: 'Center' },
|
||||
];
|
||||
|
||||
export const standardFieldDisplayOptions: FieldDisplayOptions = {
|
||||
export const commonValueOptionDefaults: ReduceDataOptions = {
|
||||
values: false,
|
||||
calcs: [ReducerID.mean],
|
||||
};
|
||||
@ -50,9 +51,9 @@ export const standardFieldConfig: FieldConfigSource = {
|
||||
overrides: [],
|
||||
};
|
||||
|
||||
export function addStandardSingleValueOptions(builder: PanelOptionsEditorBuilder) {
|
||||
export function addStandardDataReduceOptions(builder: PanelOptionsEditorBuilder) {
|
||||
builder.addRadio({
|
||||
id: 'values',
|
||||
id: 'reduceOptions.values',
|
||||
name: 'Show',
|
||||
description: 'Calculate a single value per colum or series or show each row',
|
||||
settings: {
|
||||
@ -62,12 +63,44 @@ export function addStandardSingleValueOptions(builder: PanelOptionsEditorBuilder
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
builder.addNumberInput({
|
||||
id: 'reduceOptions.limit',
|
||||
name: 'Limit',
|
||||
description: 'Max number of rows to display',
|
||||
settings: {
|
||||
placeholder: '5000',
|
||||
integer: true,
|
||||
min: 1,
|
||||
max: 5000,
|
||||
},
|
||||
});
|
||||
|
||||
builder.addCustomEditor({
|
||||
id: 'reduceOptions.calcs',
|
||||
name: 'Value',
|
||||
description: 'Choose a reducer function / calculation',
|
||||
editor: standardEditorsRegistry.get('stats-picker').editor as any,
|
||||
});
|
||||
|
||||
builder.addRadio({
|
||||
id: 'orientation',
|
||||
name: 'Orientation',
|
||||
description: 'Stacking direction in case of multiple series or fields',
|
||||
settings: {
|
||||
options: [
|
||||
{ value: 'auto', label: 'Auto' },
|
||||
{ value: 'horizontal', label: 'Horizontal' },
|
||||
{ value: 'vertical', label: 'Vertical' },
|
||||
],
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export const defaults: StatPanelOptions = {
|
||||
graphMode: BigValueGraphMode.Area,
|
||||
colorMode: BigValueColorMode.Value,
|
||||
justifyMode: BigValueJustifyMode.Auto,
|
||||
fieldOptions: standardFieldDisplayOptions,
|
||||
reduceOptions: commonValueOptionDefaults,
|
||||
orientation: VizOrientation.Auto,
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user