mirror of
https://github.com/grafana/grafana.git
synced 2025-02-11 08:05:43 -06:00
Candlestick: exclude unmapped fields by default (#42011)
Co-authored-by: Leon Sorokin <leeoniya@gmail.com>
This commit is contained in:
parent
8a06e89d2f
commit
403222e14e
@ -320,11 +320,14 @@ export const preparePlotConfigBuilder: UPlotConfigPrepFn<{ sync: DashboardCursor
|
||||
|
||||
// hook up custom/composite renderers
|
||||
renderers?.forEach((r) => {
|
||||
if (!indexByName) {
|
||||
indexByName = getNamesToFieldIndex(frame, allFrames);
|
||||
}
|
||||
let fieldIndices: Record<string, number> = {};
|
||||
|
||||
for (let key in r.fieldMap) {
|
||||
let dispName = r.fieldMap[key];
|
||||
fieldIndices[key] = indexByName!.get(dispName)!;
|
||||
fieldIndices[key] = indexByName.get(dispName)!;
|
||||
}
|
||||
|
||||
r.init(builder, fieldIndices);
|
||||
|
@ -21,7 +21,7 @@ import uPlot from 'uplot';
|
||||
|
||||
interface CandlestickPanelProps extends PanelProps<CandlestickOptions> {}
|
||||
|
||||
export const MarketTrendPanel: React.FC<CandlestickPanelProps> = ({
|
||||
export const CandlestickPanel: React.FC<CandlestickPanelProps> = ({
|
||||
data,
|
||||
timeRange,
|
||||
timeZone,
|
||||
|
@ -9,7 +9,7 @@ import {
|
||||
} from '@grafana/data';
|
||||
import { findField } from 'app/features/dimensions';
|
||||
import { prepareGraphableFields } from '../timeseries/utils';
|
||||
import { CandlestickOptions, CandlestickFieldMap } from './models.gen';
|
||||
import { CandlestickOptions, CandlestickFieldMap, VizDisplayMode } from './models.gen';
|
||||
|
||||
export interface FieldPickerInfo {
|
||||
/** property name */
|
||||
@ -115,12 +115,18 @@ export function prepareCandlestickFields(
|
||||
if (norm.warn || norm.noTimeField || !norm.frames?.length) {
|
||||
return norm as CandlestickData;
|
||||
}
|
||||
data.frame = norm.frames[0];
|
||||
const frame = (data.frame = norm.frames[0]);
|
||||
const timeIndex = frame.fields.findIndex((f) => f.type === FieldType.time);
|
||||
if (timeIndex < 0) {
|
||||
data.warn = 'Missing time field';
|
||||
data.noTimeField = true;
|
||||
return data;
|
||||
}
|
||||
|
||||
// Find the known fields
|
||||
const used = new Set<Field>();
|
||||
for (const info of Object.values(candlestickFieldsInfo)) {
|
||||
const field = findFieldOrAuto(data.frame, info, fieldMap);
|
||||
const field = findFieldOrAuto(frame, info, fieldMap);
|
||||
if (field) {
|
||||
data[info.key] = field;
|
||||
used.add(field);
|
||||
@ -129,7 +135,7 @@ export function prepareCandlestickFields(
|
||||
|
||||
// Use first numeric value as open
|
||||
if (!data.open && !data.close) {
|
||||
data.open = data.frame.fields.find((f) => f.type === FieldType.number);
|
||||
data.open = frame.fields.find((f) => f.type === FieldType.number);
|
||||
if (data.open) {
|
||||
used.add(data.open);
|
||||
}
|
||||
@ -145,7 +151,8 @@ export function prepareCandlestickFields(
|
||||
name: 'Next open',
|
||||
state: undefined,
|
||||
};
|
||||
data.frame.fields.push(data.close);
|
||||
used.add(data.close);
|
||||
frame.fields.push(data.close);
|
||||
data.autoOpenClose = true;
|
||||
}
|
||||
|
||||
@ -153,14 +160,15 @@ export function prepareCandlestickFields(
|
||||
if (data.close && !data.open && !fieldMap.open) {
|
||||
const values = data.close.values.toArray().slice();
|
||||
values.unshift(values[0]); // duplicate first value
|
||||
values.length = data.frame.length;
|
||||
values.length = frame.length;
|
||||
data.open = {
|
||||
...data.close,
|
||||
values: new ArrayVector(values),
|
||||
name: 'Previous close',
|
||||
state: undefined,
|
||||
};
|
||||
data.frame.fields.push(data.open);
|
||||
used.add(data.open);
|
||||
frame.fields.push(data.open);
|
||||
data.autoOpenClose = true;
|
||||
}
|
||||
|
||||
@ -172,6 +180,24 @@ export function prepareCandlestickFields(
|
||||
data.low = data.open;
|
||||
}
|
||||
|
||||
// unmap low and high fields in volume-only mode, and volume field in candles-only mode
|
||||
// so they fall through to unmapped fields and get appropriate includeAllFields treatment
|
||||
if (options.mode === VizDisplayMode.Volume) {
|
||||
if (data.high) {
|
||||
used.delete(data.high);
|
||||
data.high = undefined;
|
||||
}
|
||||
if (data.low) {
|
||||
used.delete(data.low);
|
||||
data.low = undefined;
|
||||
}
|
||||
} else if (options.mode === VizDisplayMode.Candles) {
|
||||
if (data.volume) {
|
||||
used.delete(data.volume);
|
||||
data.volume = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
// Register the name of each mapped field
|
||||
for (const info of Object.values(candlestickFieldsInfo)) {
|
||||
const f = data[info.key];
|
||||
@ -180,5 +206,34 @@ export function prepareCandlestickFields(
|
||||
}
|
||||
}
|
||||
|
||||
const timeField = frame.fields[timeIndex];
|
||||
|
||||
// Make sure first field is time!
|
||||
const fields: Field[] = [timeField];
|
||||
|
||||
if (!options.includeAllFields) {
|
||||
fields.push(...used);
|
||||
} else if (timeIndex > 0) {
|
||||
fields.push(...frame.fields.filter((f) => f !== timeField));
|
||||
}
|
||||
|
||||
data.frame = {
|
||||
...data.frame,
|
||||
fields,
|
||||
};
|
||||
|
||||
// Force update all the indicies
|
||||
for (let i = 0; i < data.frame.fields.length; i++) {
|
||||
const field = data.frame.fields[i];
|
||||
|
||||
// time is unused (-1), y series enumerate from 0
|
||||
field.state!.seriesIndex = i - 1;
|
||||
|
||||
field.state!.origin = {
|
||||
fieldIndex: i,
|
||||
frameIndex: 0,
|
||||
};
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
@ -53,6 +53,9 @@ export interface CandlestickOptions extends OptionsWithLegend {
|
||||
colorStrategy: ColorStrategy;
|
||||
fields: CandlestickFieldMap;
|
||||
colors: CandlestickColors;
|
||||
|
||||
// When enabled, all fields will be sent to the graph
|
||||
includeAllFields?: boolean;
|
||||
}
|
||||
|
||||
export const defaultPanelOptions: CandlestickOptions = {
|
||||
@ -66,4 +69,5 @@ export const defaultPanelOptions: CandlestickOptions = {
|
||||
placement: 'bottom',
|
||||
calcs: [],
|
||||
},
|
||||
includeAllFields: false,
|
||||
};
|
||||
|
@ -8,7 +8,7 @@ import {
|
||||
SelectableValue,
|
||||
} from '@grafana/data';
|
||||
import { commonOptionsBuilder } from '@grafana/ui';
|
||||
import { MarketTrendPanel } from './CandlestickPanel';
|
||||
import { CandlestickPanel } from './CandlestickPanel';
|
||||
import {
|
||||
defaultColors,
|
||||
CandlestickOptions,
|
||||
@ -68,7 +68,7 @@ function addFieldPicker(
|
||||
});
|
||||
}
|
||||
|
||||
export const plugin = new PanelPlugin<CandlestickOptions, GraphFieldConfig>(MarketTrendPanel)
|
||||
export const plugin = new PanelPlugin<CandlestickOptions, GraphFieldConfig>(CandlestickPanel)
|
||||
.useFieldConfig(getGraphFieldConfig(defaultGraphConfig))
|
||||
.setPanelOptions((builder, context) => {
|
||||
const opts = context.options ?? defaultPanelOptions;
|
||||
@ -125,6 +125,19 @@ export const plugin = new PanelPlugin<CandlestickOptions, GraphFieldConfig>(Mark
|
||||
addFieldPicker(builder, candlestickFieldsInfo.volume, info);
|
||||
}
|
||||
|
||||
builder.addRadio({
|
||||
path: 'includeAllFields',
|
||||
name: 'Additional fields',
|
||||
description: 'Use standard timeseries options to configure any fields not mapped above',
|
||||
defaultValue: defaultPanelOptions.includeAllFields,
|
||||
settings: {
|
||||
options: [
|
||||
{ label: 'Ignore', value: false },
|
||||
{ label: 'Include', value: true },
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
// commonOptionsBuilder.addTooltipOptions(builder);
|
||||
commonOptionsBuilder.addLegendOptions(builder);
|
||||
})
|
||||
|
Loading…
Reference in New Issue
Block a user