grafana/public/app/plugins/panel/xychart/dims.ts
Oscar Kilhed f3aa058886
XY Panel: Add and use schema for XY Panel configuration (#62148)
* Add schema for XYChart

* Minor cleanup

* remove unessecary fields from ScatterFieldConfigVeneer, and cleaning up more

* Fix counts

Co-authored-by: sam boyer <sdboyer@grafana.com>
2023-01-25 22:29:07 +00:00

104 lines
2.3 KiB
TypeScript

import { DataFrame, Field, FieldMatcher, FieldType, getFieldDisplayName } from '@grafana/data';
import { XYFieldMatchers } from '@grafana/ui/src/components/GraphNG/types';
import { XYDimensionConfig } from './types';
// TODO: fix import
export enum DimensionError {
NoData,
BadFrameSelection,
XNotFound,
}
export interface XYDimensions {
frame: DataFrame; // matches order from configs, excluds non-graphable values
x: Field;
fields: XYFieldMatchers;
error?: DimensionError;
hasData?: boolean;
hasTime?: boolean;
}
export function isGraphable(field: Field) {
return field.type === FieldType.number;
}
export function getXYDimensions(cfg?: XYDimensionConfig, data?: DataFrame[]): XYDimensions {
if (!data || !data.length) {
return { error: DimensionError.NoData } as XYDimensions;
}
if (!cfg) {
cfg = {
frame: 0,
};
}
let frame = data[cfg.frame ?? 0];
if (!frame) {
return { error: DimensionError.BadFrameSelection } as XYDimensions;
}
let xIndex = -1;
for (let i = 0; i < frame.fields.length; i++) {
const f = frame.fields[i];
if (cfg.x && cfg.x === getFieldDisplayName(f, frame, data)) {
xIndex = i;
break;
}
if (isGraphable(f) && !cfg.x) {
xIndex = i;
break;
}
}
let hasTime = false;
const x = frame.fields[xIndex];
const fields: Field[] = [x];
for (const f of frame.fields) {
if (f.type === FieldType.time) {
hasTime = true;
}
if (f === x || !isGraphable(f)) {
continue;
}
if (cfg.exclude) {
const name = getFieldDisplayName(f, frame, data);
if (cfg.exclude.includes(name)) {
continue;
}
}
fields.push(f);
}
return {
x,
fields: {
x: getSimpleFieldMatcher(x),
y: getSimpleFieldNotMatcher(x), // Not x
},
frame: {
...frame,
fields,
},
hasData: frame.fields.length > 0,
hasTime,
};
}
function getSimpleFieldMatcher(f: Field): FieldMatcher {
if (!f) {
return () => false;
}
// the field may change if sorted
return (field) => f === field || !!(f.state && f.state === field.state);
}
function getSimpleFieldNotMatcher(f: Field): FieldMatcher {
if (!f) {
return () => false;
}
const m = getSimpleFieldMatcher(f);
return (field) => !m(field, undefined as any, undefined as any);
}