mirror of
https://github.com/grafana/grafana.git
synced 2025-08-06 18:24:20 +08:00
BarGauge: First bar gauge panel option & some refactoring (#23128)
* First bar gauge panel option * Update doc comments * Minor changes * progress * Fixing typing errors * Minor type updates * Fix that TS! * Bring satisfaction to that beast called typescript Co-authored-by: Dominik Prokop <dominik.prokop@grafana.com>
This commit is contained in:
@ -15,10 +15,10 @@ export interface NumberFieldConfigSettings {
|
|||||||
export const numberOverrideProcessor = (
|
export const numberOverrideProcessor = (
|
||||||
value: any,
|
value: any,
|
||||||
context: FieldOverrideContext,
|
context: FieldOverrideContext,
|
||||||
settings: NumberFieldConfigSettings
|
settings?: NumberFieldConfigSettings
|
||||||
) => {
|
) => {
|
||||||
const v = parseFloat(`${value}`);
|
const v = parseFloat(`${value}`);
|
||||||
if (settings.max && v > settings.max) {
|
if (settings && settings.max && v > settings.max) {
|
||||||
// ????
|
// ????
|
||||||
}
|
}
|
||||||
return v;
|
return v;
|
||||||
@ -29,7 +29,7 @@ export interface DataLinksFieldConfigSettings {}
|
|||||||
export const dataLinksOverrideProcessor = (
|
export const dataLinksOverrideProcessor = (
|
||||||
value: any,
|
value: any,
|
||||||
_context: FieldOverrideContext,
|
_context: FieldOverrideContext,
|
||||||
_settings: DataLinksFieldConfigSettings
|
_settings?: DataLinksFieldConfigSettings
|
||||||
) => {
|
) => {
|
||||||
return value as DataLink[];
|
return value as DataLink[];
|
||||||
};
|
};
|
||||||
@ -39,7 +39,7 @@ export interface ValueMappingFieldConfigSettings {}
|
|||||||
export const valueMappingsOverrideProcessor = (
|
export const valueMappingsOverrideProcessor = (
|
||||||
value: any,
|
value: any,
|
||||||
_context: FieldOverrideContext,
|
_context: FieldOverrideContext,
|
||||||
_settings: ValueMappingFieldConfigSettings
|
_settings?: ValueMappingFieldConfigSettings
|
||||||
) => {
|
) => {
|
||||||
return value as ValueMapping[]; // !!!! likely not !!!!
|
return value as ValueMapping[]; // !!!! likely not !!!!
|
||||||
};
|
};
|
||||||
@ -51,7 +51,7 @@ export interface SelectFieldConfigSettings<T> {
|
|||||||
export const selectOverrideProcessor = (
|
export const selectOverrideProcessor = (
|
||||||
value: any,
|
value: any,
|
||||||
_context: FieldOverrideContext,
|
_context: FieldOverrideContext,
|
||||||
_settings: SelectFieldConfigSettings<any>
|
_settings?: SelectFieldConfigSettings<any>
|
||||||
) => {
|
) => {
|
||||||
return value;
|
return value;
|
||||||
};
|
};
|
||||||
@ -65,9 +65,9 @@ export interface StringFieldConfigSettings {
|
|||||||
export const stringOverrideProcessor = (
|
export const stringOverrideProcessor = (
|
||||||
value: any,
|
value: any,
|
||||||
context: FieldOverrideContext,
|
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 context.replaceVariables(value, context.field!.config.scopedVars);
|
||||||
}
|
}
|
||||||
return `${value}`;
|
return `${value}`;
|
||||||
@ -80,7 +80,7 @@ export interface ThresholdsFieldConfigSettings {
|
|||||||
export const thresholdsOverrideProcessor = (
|
export const thresholdsOverrideProcessor = (
|
||||||
value: any,
|
value: any,
|
||||||
_context: FieldOverrideContext,
|
_context: FieldOverrideContext,
|
||||||
_settings: ThresholdsFieldConfigSettings
|
_settings?: ThresholdsFieldConfigSettings
|
||||||
) => {
|
) => {
|
||||||
return value as ThresholdsConfig; // !!!! likely not !!!!
|
return value as ThresholdsConfig; // !!!! likely not !!!!
|
||||||
};
|
};
|
||||||
@ -90,7 +90,7 @@ export interface UnitFieldConfigSettings {}
|
|||||||
export const unitOverrideProcessor = (
|
export const unitOverrideProcessor = (
|
||||||
value: boolean,
|
value: boolean,
|
||||||
_context: FieldOverrideContext,
|
_context: FieldOverrideContext,
|
||||||
_settings: UnitFieldConfigSettings
|
_settings?: UnitFieldConfigSettings
|
||||||
) => {
|
) => {
|
||||||
return value;
|
return value;
|
||||||
};
|
};
|
||||||
@ -98,7 +98,7 @@ export const unitOverrideProcessor = (
|
|||||||
export const booleanOverrideProcessor = (
|
export const booleanOverrideProcessor = (
|
||||||
value: boolean,
|
value: boolean,
|
||||||
_context: FieldOverrideContext,
|
_context: FieldOverrideContext,
|
||||||
_settings: ThresholdsFieldConfigSettings
|
_settings?: ThresholdsFieldConfigSettings
|
||||||
) => {
|
) => {
|
||||||
return value; // !!!! likely not !!!!
|
return value; // !!!! likely not !!!!
|
||||||
};
|
};
|
||||||
|
@ -9,7 +9,7 @@ describe('PanelPlugin', () => {
|
|||||||
return <div>Panel</div>;
|
return <div>Panel</div>;
|
||||||
});
|
});
|
||||||
|
|
||||||
panel.setCustomFieldConfigEditor(builder => {
|
panel.setCustomFieldOptions(builder => {
|
||||||
builder.addCustomEditor({
|
builder.addCustomEditor({
|
||||||
id: 'custom',
|
id: 'custom',
|
||||||
name: 'Custom',
|
name: 'Custom',
|
||||||
@ -31,7 +31,7 @@ describe('PanelPlugin', () => {
|
|||||||
return <div>Panel</div>;
|
return <div>Panel</div>;
|
||||||
});
|
});
|
||||||
|
|
||||||
panel.setOptionsEditor(builder => {
|
panel.setPanelOptions(builder => {
|
||||||
builder.addCustomEditor({
|
builder.addCustomEditor({
|
||||||
id: 'option',
|
id: 'option',
|
||||||
name: 'Option editor',
|
name: 'Option editor',
|
||||||
|
@ -110,7 +110,7 @@ export class PanelPlugin<TOptions = any> extends GrafanaPlugin<PanelPluginMeta>
|
|||||||
* interface ShapePanelOptions {}
|
* interface ShapePanelOptions {}
|
||||||
*
|
*
|
||||||
* export const plugin = new PanelPlugin<ShapePanelOptions>(ShapePanel)
|
* export const plugin = new PanelPlugin<ShapePanelOptions>(ShapePanel)
|
||||||
* .setCustomFieldConfigEditor(builder => {
|
* .setCustomFieldOptions(builder => {
|
||||||
* builder
|
* builder
|
||||||
* .addNumberInput({
|
* .addNumberInput({
|
||||||
* id: 'shapeBorderWidth',
|
* id: 'shapeBorderWidth',
|
||||||
@ -134,7 +134,7 @@ export class PanelPlugin<TOptions = any> extends GrafanaPlugin<PanelPluginMeta>
|
|||||||
*
|
*
|
||||||
* @public
|
* @public
|
||||||
**/
|
**/
|
||||||
setCustomFieldConfigEditor(builder: (builder: FieldConfigEditorBuilder) => void) {
|
setCustomFieldOptions(builder: (builder: FieldConfigEditorBuilder) => void) {
|
||||||
// builder is applied lazily when custom field configs are accessed
|
// builder is applied lazily when custom field configs are accessed
|
||||||
this.registerCustomFieldConfigs = builder;
|
this.registerCustomFieldConfigs = builder;
|
||||||
return this;
|
return this;
|
||||||
@ -151,7 +151,7 @@ export class PanelPlugin<TOptions = any> extends GrafanaPlugin<PanelPluginMeta>
|
|||||||
* interface ShapePanelOptions {}
|
* interface ShapePanelOptions {}
|
||||||
*
|
*
|
||||||
* export const plugin = new PanelPlugin<ShapePanelOptions>(ShapePanel)
|
* export const plugin = new PanelPlugin<ShapePanelOptions>(ShapePanel)
|
||||||
* .setOptionsEditor(builder => {
|
* .setPanelOptions(builder => {
|
||||||
* builder
|
* builder
|
||||||
* .addSelect({
|
* .addSelect({
|
||||||
* id: 'shape',
|
* id: 'shape',
|
||||||
@ -170,7 +170,7 @@ export class PanelPlugin<TOptions = any> extends GrafanaPlugin<PanelPluginMeta>
|
|||||||
*
|
*
|
||||||
* @public
|
* @public
|
||||||
**/
|
**/
|
||||||
setOptionsEditor(builder: (builder: PanelOptionsEditorBuilder) => void) {
|
setPanelOptions(builder: (builder: PanelOptionsEditorBuilder) => void) {
|
||||||
// builder is applied lazily when options UI is created
|
// builder is applied lazily when options UI is created
|
||||||
this.registerOptionEditors = builder;
|
this.registerOptionEditors = builder;
|
||||||
return this;
|
return this;
|
||||||
|
@ -5,44 +5,46 @@ import { NumberFieldConfigSettings, SelectFieldConfigSettings, StringFieldConfig
|
|||||||
/**
|
/**
|
||||||
* Option editor registry item
|
* Option editor registry item
|
||||||
*/
|
*/
|
||||||
interface OptionsEditorItem<TSettings, TEditorProps> extends RegistryItem {
|
export interface OptionsEditorItem<TSettings, TEditorProps> extends RegistryItem {
|
||||||
|
editor: ComponentType<TEditorProps>;
|
||||||
settings?: TSettings;
|
settings?: TSettings;
|
||||||
editor?: ComponentType<TEditorProps>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configuration of option editor registry item
|
* Configuration of option editor registry item
|
||||||
*/
|
*/
|
||||||
type OptionEditorConfig<TSettings, TEditorProps> = Pick<
|
interface OptionEditorConfig<TSettings> {
|
||||||
OptionsEditorItem<TSettings, TEditorProps>,
|
id: string;
|
||||||
'id' | 'name' | 'description' | 'editor' | 'settings'
|
name: string;
|
||||||
>;
|
description: string;
|
||||||
|
settings?: TSettings;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Describes an API for option editors UI builder
|
* Describes an API for option editors UI builder
|
||||||
*/
|
*/
|
||||||
export interface OptionsUIRegistryBuilderAPI<TEditorProps, T extends OptionsEditorItem<any, TEditorProps>> {
|
export interface OptionsUIRegistryBuilderAPI<TEditorProps, T extends OptionsEditorItem<any, TEditorProps>> {
|
||||||
addNumberInput?<TSettings extends NumberFieldConfigSettings = NumberFieldConfigSettings>(
|
addNumberInput?<TSettings extends NumberFieldConfigSettings = NumberFieldConfigSettings>(
|
||||||
config: OptionEditorConfig<TSettings, TEditorProps>
|
config: OptionEditorConfig<TSettings>
|
||||||
): this;
|
): this;
|
||||||
|
|
||||||
addTextInput?<TSettings extends StringFieldConfigSettings = StringFieldConfigSettings>(
|
addTextInput?<TSettings extends StringFieldConfigSettings = StringFieldConfigSettings>(
|
||||||
config: OptionEditorConfig<TSettings, TEditorProps>
|
config: OptionEditorConfig<TSettings>
|
||||||
): this;
|
): this;
|
||||||
|
|
||||||
addSelect?<TOption, TSettings extends SelectFieldConfigSettings<TOption>>(
|
addSelect?<TOption, TSettings extends SelectFieldConfigSettings<TOption>>(
|
||||||
config: OptionEditorConfig<TSettings, TEditorProps>
|
config: OptionEditorConfig<TSettings>
|
||||||
): this;
|
): this;
|
||||||
|
|
||||||
addRadio?<TOption, TSettings extends SelectFieldConfigSettings<TOption> = SelectFieldConfigSettings<TOption>>(
|
addRadio?<TOption, TSettings extends SelectFieldConfigSettings<TOption> = SelectFieldConfigSettings<TOption>>(
|
||||||
config: OptionEditorConfig<TSettings, TEditorProps>
|
config: OptionEditorConfig<TSettings>
|
||||||
): this;
|
): this;
|
||||||
|
|
||||||
addBooleanSwitch?<TSettings = any>(config: OptionEditorConfig<TSettings, TEditorProps>): this;
|
addBooleanSwitch?<TSettings = any>(config: OptionEditorConfig<TSettings>): this;
|
||||||
|
|
||||||
addUnitPicker?<TSettings = any>(config: OptionEditorConfig<TSettings, TEditorProps>): this;
|
addUnitPicker?<TSettings = any>(config: OptionEditorConfig<TSettings>): this;
|
||||||
|
|
||||||
addColorPicker?<TSettings = any>(config: OptionEditorConfig<TSettings, TEditorProps>): this;
|
addColorPicker?<TSettings = any>(config: OptionEditorConfig<TSettings>): this;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enables custom editor definition
|
* Enables custom editor definition
|
||||||
|
@ -9,9 +9,10 @@ import {
|
|||||||
GrafanaTheme,
|
GrafanaTheme,
|
||||||
TimeZone,
|
TimeZone,
|
||||||
} from '../types';
|
} from '../types';
|
||||||
import { Registry, RegistryItem } from '../utils';
|
import { Registry } from '../utils';
|
||||||
import { InterpolateFunction } from './panel';
|
import { InterpolateFunction } from './panel';
|
||||||
import { StandardEditorProps } from '../field';
|
import { StandardEditorProps } from '../field';
|
||||||
|
import { OptionsEditorItem } from './OptionsUIRegistryBuilder';
|
||||||
|
|
||||||
export interface DynamicConfigValue {
|
export interface DynamicConfigValue {
|
||||||
prop: string;
|
prop: string;
|
||||||
@ -53,24 +54,21 @@ export interface FieldOverrideEditorProps<TValue, TSettings> extends Omit<Standa
|
|||||||
context: FieldOverrideContext;
|
context: FieldOverrideContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface FieldConfigEditorConfig<TSettings = any, TValue = any>
|
export interface FieldConfigEditorConfig<TSettings = any> {
|
||||||
extends Omit<Pick<FieldPropertyEditorItem<TValue, TSettings>, 'id' | 'description' | 'name'>, 'settings'> {
|
id: string;
|
||||||
|
name: string;
|
||||||
|
description: string;
|
||||||
settings?: TSettings;
|
settings?: TSettings;
|
||||||
shouldApply?: (field: Field) => boolean;
|
shouldApply?: (field: Field) => boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface FieldPropertyEditorItem<TValue = any, TSettings = any> extends RegistryItem {
|
export interface FieldPropertyEditorItem<TValue = any, TSettings extends {} = any>
|
||||||
// An editor the creates the well typed value
|
extends OptionsEditorItem<TSettings, FieldConfigEditorProps<TValue, TSettings>> {
|
||||||
editor: ComponentType<FieldConfigEditorProps<TValue, TSettings>>;
|
|
||||||
|
|
||||||
// An editor that can be filled in with context info (template variables etc)
|
// An editor that can be filled in with context info (template variables etc)
|
||||||
override: ComponentType<FieldOverrideEditorProps<TValue, TSettings>>;
|
override: ComponentType<FieldOverrideEditorProps<TValue, TSettings>>;
|
||||||
|
|
||||||
// Convert the override value to a well typed value
|
// Convert the override value to a well typed value
|
||||||
process: (value: any, context: FieldOverrideContext, settings: TSettings) => TValue;
|
process: (value: any, context: FieldOverrideContext, settings?: TSettings) => TValue;
|
||||||
|
|
||||||
// Configuration options for the particular property
|
|
||||||
settings: TSettings;
|
|
||||||
|
|
||||||
// Checks if field should be processed
|
// Checks if field should be processed
|
||||||
shouldApply: (field: Field) => boolean;
|
shouldApply: (field: Field) => boolean;
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import { ComponentType } from 'react';
|
|
||||||
import { DataQueryError, DataQueryRequest, DataQueryTimings } from './datasource';
|
import { DataQueryError, DataQueryRequest, DataQueryTimings } from './datasource';
|
||||||
import { PluginMeta } from './plugin';
|
import { PluginMeta } from './plugin';
|
||||||
import { ScopedVars } from './ScopedVars';
|
import { ScopedVars } from './ScopedVars';
|
||||||
@ -6,8 +5,9 @@ import { LoadingState } from './data';
|
|||||||
import { DataFrame } from './dataFrame';
|
import { DataFrame } from './dataFrame';
|
||||||
import { AbsoluteTimeRange, TimeRange, TimeZone } from './time';
|
import { AbsoluteTimeRange, TimeRange, TimeZone } from './time';
|
||||||
import { FieldConfigSource } from './fieldOverrides';
|
import { FieldConfigSource } from './fieldOverrides';
|
||||||
import { Registry, RegistryItem } from '../utils';
|
import { Registry } from '../utils';
|
||||||
import { StandardEditorProps } from '../field';
|
import { StandardEditorProps } from '../field';
|
||||||
|
import { OptionsEditorItem } from './OptionsUIRegistryBuilder';
|
||||||
|
|
||||||
export type InterpolateFunction = (value: string, scopedVars?: ScopedVars, format?: string | Function) => string;
|
export type InterpolateFunction = (value: string, scopedVars?: ScopedVars, format?: string | Function) => string;
|
||||||
|
|
||||||
@ -115,14 +115,16 @@ export type PanelOptionEditorsRegistry = Registry<PanelOptionsEditorItem>;
|
|||||||
|
|
||||||
export interface PanelOptionsEditorProps<TValue> extends StandardEditorProps<TValue> {}
|
export interface PanelOptionsEditorProps<TValue> extends StandardEditorProps<TValue> {}
|
||||||
|
|
||||||
export interface PanelOptionsEditorItem<TValue = any, TSettings = any> extends RegistryItem {
|
export interface PanelOptionsEditorItem<TValue = any, TSettings = any>
|
||||||
editor: ComponentType<PanelOptionsEditorProps<TValue>>;
|
extends OptionsEditorItem<TSettings, PanelOptionsEditorProps<TValue>> {}
|
||||||
|
|
||||||
|
export interface PanelOptionsEditorConfig<TSettings = any> {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
description: string;
|
||||||
settings?: TSettings;
|
settings?: TSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PanelOptionsEditorConfig<TSettings = any, TValue = any>
|
|
||||||
extends Pick<PanelOptionsEditorItem<TValue, TSettings>, 'id' | 'description' | 'name' | 'settings'> {}
|
|
||||||
|
|
||||||
export interface PanelMenuItem {
|
export interface PanelMenuItem {
|
||||||
type?: 'submenu' | 'divider';
|
type?: 'submenu' | 'divider';
|
||||||
text?: string;
|
text?: string;
|
||||||
|
@ -16,14 +16,14 @@ export const NumberValueEditor: React.FC<FieldConfigEditorProps<number, NumberFi
|
|||||||
return (
|
return (
|
||||||
<Forms.Input
|
<Forms.Input
|
||||||
value={isNaN(value) ? '' : value}
|
value={isNaN(value) ? '' : value}
|
||||||
min={settings.min}
|
min={settings?.min}
|
||||||
max={settings.max}
|
max={settings?.max}
|
||||||
type="number"
|
type="number"
|
||||||
step={settings.step}
|
step={settings?.step}
|
||||||
placeholder={settings.placeholder}
|
placeholder={settings?.placeholder}
|
||||||
onChange={e => {
|
onChange={e => {
|
||||||
onChange(
|
onChange(
|
||||||
settings.integer ? toIntegerOrUndefined(e.currentTarget.value) : toFloatOrUndefined(e.currentTarget.value)
|
settings?.integer ? toIntegerOrUndefined(e.currentTarget.value) : toFloatOrUndefined(e.currentTarget.value)
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
@ -7,5 +7,5 @@ export function SelectValueEditor<T>({
|
|||||||
onChange,
|
onChange,
|
||||||
item,
|
item,
|
||||||
}: FieldConfigEditorProps<T, SelectFieldConfigSettings<T>>) {
|
}: FieldConfigEditorProps<T, SelectFieldConfigSettings<T>>) {
|
||||||
return <Forms.Select<T> defaultValue={value} onChange={e => onChange(e.value)} options={item.settings.options} />;
|
return <Forms.Select<T> defaultValue={value} onChange={e => onChange(e.value)} options={item.settings?.options} />;
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ interface Props<V, D> {
|
|||||||
/**
|
/**
|
||||||
* Render a single value
|
* Render a single value
|
||||||
*/
|
*/
|
||||||
renderValue: (value: V, width: number, height: number, dims: D) => JSX.Element;
|
renderValue: (props: VizRepeaterRenderValueProps<V, D>) => JSX.Element;
|
||||||
height: number;
|
height: number;
|
||||||
width: number;
|
width: number;
|
||||||
source: any; // If this changes, new values will be requested
|
source: any; // If this changes, new values will be requested
|
||||||
@ -23,6 +23,14 @@ interface Props<V, D> {
|
|||||||
itemSpacing?: number;
|
itemSpacing?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface VizRepeaterRenderValueProps<V, D = {}> {
|
||||||
|
value: V;
|
||||||
|
width: number;
|
||||||
|
height: number;
|
||||||
|
orientation: VizOrientation;
|
||||||
|
alignmentFactors: D;
|
||||||
|
}
|
||||||
|
|
||||||
interface DefaultProps {
|
interface DefaultProps {
|
||||||
itemSpacing: number;
|
itemSpacing: number;
|
||||||
}
|
}
|
||||||
@ -99,13 +107,14 @@ export class VizRepeater<V, D = {}> extends PureComponent<Props<V, D>, State<V>>
|
|||||||
itemStyles.width = `${vizWidth}px`;
|
itemStyles.width = `${vizWidth}px`;
|
||||||
itemStyles.height = `${vizHeight}px`;
|
itemStyles.height = `${vizHeight}px`;
|
||||||
|
|
||||||
const dims = getAlignmentFactors ? getAlignmentFactors(values, vizWidth, vizHeight) : ({} as D);
|
const alignmentFactors = getAlignmentFactors ? getAlignmentFactors(values, vizWidth, vizHeight) : ({} as D);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={repeaterStyle}>
|
<div style={repeaterStyle}>
|
||||||
{values.map((value, index) => {
|
{values.map((value, index) => {
|
||||||
return (
|
return (
|
||||||
<div key={index} style={getItemStylesForIndex(itemStyles, index, values.length)}>
|
<div key={index} style={getItemStylesForIndex(itemStyles, index, values.length)}>
|
||||||
{renderValue(value, vizWidth, vizHeight, dims)}
|
{renderValue({ value, width: vizWidth, height: vizHeight, alignmentFactors, orientation })}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
@ -78,7 +78,7 @@ export { GraphWithLegend } from './Graph/GraphWithLegend';
|
|||||||
export { GraphContextMenu } from './Graph/GraphContextMenu';
|
export { GraphContextMenu } from './Graph/GraphContextMenu';
|
||||||
export { BarGauge, BarGaugeDisplayMode } from './BarGauge/BarGauge';
|
export { BarGauge, BarGaugeDisplayMode } from './BarGauge/BarGauge';
|
||||||
export { GraphTooltipOptions } from './Graph/GraphTooltip/types';
|
export { GraphTooltipOptions } from './Graph/GraphTooltip/types';
|
||||||
export { VizRepeater } from './VizRepeater/VizRepeater';
|
export { VizRepeater, VizRepeaterRenderValueProps } from './VizRepeater/VizRepeater';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
LegendOptions,
|
LegendOptions,
|
||||||
|
@ -315,6 +315,7 @@ export const PanelEditor = connect(mapStateToProps, mapDispatchToProps)(PanelEdi
|
|||||||
*/
|
*/
|
||||||
const getStyles = stylesFactory((theme: GrafanaTheme) => {
|
const getStyles = stylesFactory((theme: GrafanaTheme) => {
|
||||||
const handleColor = theme.colors.blueLight;
|
const handleColor = theme.colors.blueLight;
|
||||||
|
const paneSpaceing = theme.spacing.md;
|
||||||
|
|
||||||
const resizer = css`
|
const resizer = css`
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
@ -354,21 +355,21 @@ const getStyles = stylesFactory((theme: GrafanaTheme) => {
|
|||||||
`,
|
`,
|
||||||
panelWrapper: css`
|
panelWrapper: css`
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding-left: ${theme.spacing.sm};
|
padding-left: ${paneSpaceing};
|
||||||
height: 100%;
|
height: 100%;
|
||||||
`,
|
`,
|
||||||
resizerV: cx(
|
resizerV: cx(
|
||||||
resizer,
|
resizer,
|
||||||
css`
|
css`
|
||||||
cursor: col-resize;
|
cursor: col-resize;
|
||||||
width: 8px;
|
width: ${paneSpaceing};
|
||||||
border-right-width: 1px;
|
border-right-width: 1px;
|
||||||
`
|
`
|
||||||
),
|
),
|
||||||
resizerH: cx(
|
resizerH: cx(
|
||||||
resizer,
|
resizer,
|
||||||
css`
|
css`
|
||||||
height: 8px;
|
height: ${paneSpaceing};
|
||||||
cursor: row-resize;
|
cursor: row-resize;
|
||||||
position: relative;
|
position: relative;
|
||||||
top: 49px;
|
top: 49px;
|
||||||
|
@ -4,7 +4,7 @@ import React, { PureComponent } from 'react';
|
|||||||
// Services & Utils
|
// Services & Utils
|
||||||
import { config } from 'app/core/config';
|
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 { BarGaugeOptions } from './types';
|
||||||
import {
|
import {
|
||||||
getFieldDisplayValues,
|
getFieldDisplayValues,
|
||||||
@ -16,13 +16,9 @@ import {
|
|||||||
import { getFieldLinksSupplier } from 'app/features/panel/panellinks/linkSuppliers';
|
import { getFieldLinksSupplier } from 'app/features/panel/panellinks/linkSuppliers';
|
||||||
|
|
||||||
export class BarGaugePanel extends PureComponent<PanelProps<BarGaugeOptions>> {
|
export class BarGaugePanel extends PureComponent<PanelProps<BarGaugeOptions>> {
|
||||||
renderValue = (
|
renderValue = (valueProps: VizRepeaterRenderValueProps<FieldDisplay, DisplayValueAlignmentFactors>): JSX.Element => {
|
||||||
value: FieldDisplay,
|
|
||||||
width: number,
|
|
||||||
height: number,
|
|
||||||
alignmentFactors: DisplayValueAlignmentFactors
|
|
||||||
): JSX.Element => {
|
|
||||||
const { options } = this.props;
|
const { options } = this.props;
|
||||||
|
const { value, alignmentFactors, orientation, width, height } = valueProps;
|
||||||
const { field, display, view, colIndex } = value;
|
const { field, display, view, colIndex } = value;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -33,7 +29,7 @@ export class BarGaugePanel extends PureComponent<PanelProps<BarGaugeOptions>> {
|
|||||||
value={display}
|
value={display}
|
||||||
width={width}
|
width={width}
|
||||||
height={height}
|
height={height}
|
||||||
orientation={options.orientation}
|
orientation={orientation}
|
||||||
field={field}
|
field={field}
|
||||||
display={view?.getFieldDisplayProcessor(colIndex)}
|
display={view?.getFieldDisplayProcessor(colIndex)}
|
||||||
theme={config.theme}
|
theme={config.theme}
|
||||||
|
@ -95,6 +95,10 @@ export class BarGaugePanelEditor extends PureComponent<PanelEditorProps<BarGauge
|
|||||||
return (
|
return (
|
||||||
<NewPanelEditorContext.Consumer>
|
<NewPanelEditorContext.Consumer>
|
||||||
{useNewEditor => {
|
{useNewEditor => {
|
||||||
|
if (useNewEditor) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<PanelOptionsGrid>
|
<PanelOptionsGrid>
|
||||||
@ -135,38 +139,28 @@ export class BarGaugePanelEditor extends PureComponent<PanelEditorProps<BarGauge
|
|||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
</PanelOptionsGroup>
|
</PanelOptionsGroup>
|
||||||
<>
|
<PanelOptionsGroup title="Field">
|
||||||
{!useNewEditor && (
|
<FieldPropertiesEditor
|
||||||
<>
|
showMinMax={true}
|
||||||
<PanelOptionsGroup title="Field">
|
showTitle={true}
|
||||||
<FieldPropertiesEditor
|
onChange={this.onDefaultsChange}
|
||||||
showMinMax={true}
|
value={defaults}
|
||||||
showTitle={true}
|
|
||||||
onChange={this.onDefaultsChange}
|
|
||||||
value={defaults}
|
|
||||||
/>
|
|
||||||
</PanelOptionsGroup>
|
|
||||||
|
|
||||||
<ThresholdsEditor onChange={this.onThresholdsChanged} thresholds={defaults.thresholds} />
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
</PanelOptionsGrid>
|
|
||||||
|
|
||||||
{!useNewEditor && (
|
|
||||||
<LegacyValueMappingsEditor onChange={this.onValueMappingsChanged} valueMappings={defaults.mappings} />
|
|
||||||
)}
|
|
||||||
|
|
||||||
{!useNewEditor && (
|
|
||||||
<PanelOptionsGroup title="Data links">
|
|
||||||
<DataLinksEditor
|
|
||||||
value={defaults.links}
|
|
||||||
onChange={this.onDataLinksChanged}
|
|
||||||
suggestions={suggestions}
|
|
||||||
maxLinks={10}
|
|
||||||
/>
|
/>
|
||||||
</PanelOptionsGroup>
|
</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,14 +1,30 @@
|
|||||||
import { sharedSingleStatPanelChangedHandler } from '@grafana/ui';
|
import { sharedSingleStatPanelChangedHandler } from '@grafana/ui';
|
||||||
import { PanelPlugin } from '@grafana/data';
|
import { PanelPlugin } from '@grafana/data';
|
||||||
import { BarGaugePanel } from './BarGaugePanel';
|
import { BarGaugePanel } from './BarGaugePanel';
|
||||||
import { BarGaugePanelEditor } from './BarGaugePanelEditor';
|
|
||||||
import { BarGaugeOptions, defaults } from './types';
|
import { BarGaugeOptions, defaults } from './types';
|
||||||
import { standardFieldConfig } from '../stat/types';
|
import { standardFieldConfig } from '../stat/types';
|
||||||
|
import { BarGaugePanelEditor } from './BarGaugePanelEditor';
|
||||||
import { barGaugePanelMigrationHandler } from './BarGaugeMigrations';
|
import { barGaugePanelMigrationHandler } from './BarGaugeMigrations';
|
||||||
|
|
||||||
export const plugin = new PanelPlugin<BarGaugeOptions>(BarGaugePanel)
|
export const plugin = new PanelPlugin<BarGaugeOptions>(BarGaugePanel)
|
||||||
.setDefaults(defaults)
|
.setDefaults(defaults)
|
||||||
.setFieldConfigDefaults(standardFieldConfig)
|
|
||||||
.setEditor(BarGaugePanelEditor)
|
.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)
|
.setPanelChangeHandler(sharedSingleStatPanelChangedHandler)
|
||||||
.setMigrationHandler(barGaugePanelMigrationHandler);
|
.setMigrationHandler(barGaugePanelMigrationHandler);
|
||||||
|
@ -5,17 +5,17 @@ import React, { PureComponent } from 'react';
|
|||||||
import { config } from 'app/core/config';
|
import { config } from 'app/core/config';
|
||||||
|
|
||||||
// Components
|
// Components
|
||||||
import { Gauge, DataLinksContextMenu } from '@grafana/ui';
|
import { Gauge, DataLinksContextMenu, VizRepeater, VizRepeaterRenderValueProps } from '@grafana/ui';
|
||||||
|
|
||||||
// Types
|
// Types
|
||||||
import { GaugeOptions } from './types';
|
import { GaugeOptions } from './types';
|
||||||
import { VizRepeater } from '@grafana/ui';
|
|
||||||
import { FieldDisplay, getFieldDisplayValues, VizOrientation, PanelProps } from '@grafana/data';
|
import { FieldDisplay, getFieldDisplayValues, VizOrientation, PanelProps } from '@grafana/data';
|
||||||
import { getFieldLinksSupplier } from 'app/features/panel/panellinks/linkSuppliers';
|
import { getFieldLinksSupplier } from 'app/features/panel/panellinks/linkSuppliers';
|
||||||
|
|
||||||
export class GaugePanel extends PureComponent<PanelProps<GaugeOptions>> {
|
export class GaugePanel extends PureComponent<PanelProps<GaugeOptions>> {
|
||||||
renderValue = (value: FieldDisplay, width: number, height: number): JSX.Element => {
|
renderValue = (valueProps: VizRepeaterRenderValueProps<FieldDisplay>): JSX.Element => {
|
||||||
const { options } = this.props;
|
const { options } = this.props;
|
||||||
|
const { value, width, height } = valueProps;
|
||||||
const { field, display } = value;
|
const { field, display } = value;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -6,7 +6,14 @@ import { config } from 'app/core/config';
|
|||||||
|
|
||||||
// Types
|
// Types
|
||||||
import { StatPanelOptions } from './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 {
|
import {
|
||||||
PanelProps,
|
PanelProps,
|
||||||
@ -21,13 +28,9 @@ import {
|
|||||||
import { getFieldLinksSupplier } from 'app/features/panel/panellinks/linkSuppliers';
|
import { getFieldLinksSupplier } from 'app/features/panel/panellinks/linkSuppliers';
|
||||||
|
|
||||||
export class StatPanel extends PureComponent<PanelProps<StatPanelOptions>> {
|
export class StatPanel extends PureComponent<PanelProps<StatPanelOptions>> {
|
||||||
renderValue = (
|
renderValue = (valueProps: VizRepeaterRenderValueProps<FieldDisplay, DisplayValueAlignmentFactors>): JSX.Element => {
|
||||||
value: FieldDisplay,
|
|
||||||
width: number,
|
|
||||||
height: number,
|
|
||||||
alignmentFactors: DisplayValueAlignmentFactors
|
|
||||||
): JSX.Element => {
|
|
||||||
const { timeRange, options } = this.props;
|
const { timeRange, options } = this.props;
|
||||||
|
const { value, alignmentFactors, width, height } = valueProps;
|
||||||
let sparkline: BigValueSparkline | undefined;
|
let sparkline: BigValueSparkline | undefined;
|
||||||
|
|
||||||
if (value.sparkline) {
|
if (value.sparkline) {
|
||||||
|
@ -7,6 +7,7 @@ import {
|
|||||||
FieldConfigSource,
|
FieldConfigSource,
|
||||||
ThresholdsMode,
|
ThresholdsMode,
|
||||||
} from '@grafana/data';
|
} from '@grafana/data';
|
||||||
|
import { PanelOptionsEditorBuilder } from '@grafana/data/src/utils/OptionsUIBuilders';
|
||||||
|
|
||||||
// Structure copied from angular
|
// Structure copied from angular
|
||||||
export interface StatPanelOptions extends SingleStatBaseOptions {
|
export interface StatPanelOptions extends SingleStatBaseOptions {
|
||||||
@ -49,6 +50,20 @@ export const standardFieldConfig: FieldConfigSource = {
|
|||||||
overrides: [],
|
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 = {
|
export const defaults: StatPanelOptions = {
|
||||||
graphMode: BigValueGraphMode.Area,
|
graphMode: BigValueGraphMode.Area,
|
||||||
colorMode: BigValueColorMode.Value,
|
colorMode: BigValueColorMode.Value,
|
||||||
|
@ -8,20 +8,18 @@ import { Options } from './types';
|
|||||||
|
|
||||||
interface Props extends PanelProps<Options> {}
|
interface Props extends PanelProps<Options> {}
|
||||||
|
|
||||||
const paddingBottom = 16;
|
|
||||||
|
|
||||||
export class TablePanel extends Component<Props> {
|
export class TablePanel extends Component<Props> {
|
||||||
constructor(props: Props) {
|
constructor(props: Props) {
|
||||||
super(props);
|
super(props);
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { data, height, width } = this.props;
|
const { data, height, width, options } = this.props;
|
||||||
|
|
||||||
if (data.series.length < 1) {
|
if (data.series.length < 1) {
|
||||||
return <div>No Table Data...</div>;
|
return <div>No Table Data...</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
return <Table height={height - paddingBottom} width={width} data={data.series[0]} />;
|
return <Table height={height} width={width} data={data.series[0]} noHeader={!options.showHeader} />;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ import { Options, defaults } from './types';
|
|||||||
|
|
||||||
export const plugin = new PanelPlugin<Options>(TablePanel)
|
export const plugin = new PanelPlugin<Options>(TablePanel)
|
||||||
.setDefaults(defaults)
|
.setDefaults(defaults)
|
||||||
.setCustomFieldConfigEditor(builder => {
|
.setCustomFieldOptions(builder => {
|
||||||
builder
|
builder
|
||||||
.addNumberInput({
|
.addNumberInput({
|
||||||
id: 'width',
|
id: 'width',
|
||||||
@ -20,7 +20,6 @@ export const plugin = new PanelPlugin<Options>(TablePanel)
|
|||||||
id: 'displayMode',
|
id: 'displayMode',
|
||||||
name: 'Cell display mode',
|
name: 'Cell display mode',
|
||||||
description: 'Color value, background, show as gauge, etc',
|
description: 'Color value, background, show as gauge, etc',
|
||||||
|
|
||||||
settings: {
|
settings: {
|
||||||
options: [
|
options: [
|
||||||
{ value: 'auto', label: 'Auto' },
|
{ value: 'auto', label: 'Auto' },
|
||||||
@ -31,7 +30,7 @@ export const plugin = new PanelPlugin<Options>(TablePanel)
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.setOptionsEditor(builder => {
|
.setPanelOptions(builder => {
|
||||||
builder.addBooleanSwitch({
|
builder.addBooleanSwitch({
|
||||||
id: 'showHeader',
|
id: 'showHeader',
|
||||||
name: 'Show header',
|
name: 'Show header',
|
||||||
|
Reference in New Issue
Block a user