mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
DataFrames: add utility function to check if structure has changed (#29006)
* add common flag for knowing if the structure changes * remove property * fix test * fix test * update comment * fix jsdoc comments
This commit is contained in:
parent
01df8f177c
commit
88b59ae3c7
95
packages/grafana-data/src/dataframe/frameComparisons.test.ts
Normal file
95
packages/grafana-data/src/dataframe/frameComparisons.test.ts
Normal file
@ -0,0 +1,95 @@
|
||||
import { FieldType } from '../types/dataFrame';
|
||||
import { compareDataFrameStructures, compareArrayValues } from './frameComparisons';
|
||||
import { toDataFrame } from './processDataFrame';
|
||||
|
||||
describe('test comparisons', () => {
|
||||
const frameA = toDataFrame({
|
||||
fields: [
|
||||
{ name: 'time', type: FieldType.time, values: [100, 200, 300] },
|
||||
{ name: 'name', type: FieldType.string, values: ['a', 'b', 'c'] },
|
||||
{ name: 'value', type: FieldType.number, values: [1, 2, 3] },
|
||||
],
|
||||
});
|
||||
const frameB = toDataFrame({
|
||||
fields: [
|
||||
{ name: 'time', type: FieldType.time, values: [100, 200, 300] },
|
||||
{
|
||||
name: 'value',
|
||||
type: FieldType.number,
|
||||
values: [1, 2, 3],
|
||||
config: {
|
||||
decimals: 4,
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
const field0 = frameB.fields[0];
|
||||
const field1 = frameB.fields[1];
|
||||
|
||||
it('should support null/undefined without crash', () => {
|
||||
expect(compareDataFrameStructures(frameA, frameA)).toBeTruthy();
|
||||
expect(compareDataFrameStructures(frameA, { ...frameA })).toBeTruthy();
|
||||
expect(compareDataFrameStructures(frameA, frameB)).toBeFalsy();
|
||||
expect(compareDataFrameStructures(frameA, null as any)).toBeFalsy();
|
||||
expect(compareDataFrameStructures(undefined as any, frameA)).toBeFalsy();
|
||||
|
||||
expect(compareArrayValues([frameA], [frameA], compareDataFrameStructures)).toBeTruthy();
|
||||
expect(compareArrayValues([frameA], null as any, compareDataFrameStructures)).toBeFalsy();
|
||||
expect(compareArrayValues(null as any, [frameA], compareDataFrameStructures)).toBeFalsy();
|
||||
});
|
||||
|
||||
it('name change and field copy is not a structure change', () => {
|
||||
expect(compareDataFrameStructures(frameB, { ...frameB, name: 'AA' })).toBeTruthy();
|
||||
expect(compareDataFrameStructures(frameB, { ...frameB, fields: [field0, field1] })).toBeTruthy();
|
||||
});
|
||||
|
||||
it('changing type should change the config', () => {
|
||||
expect(
|
||||
compareDataFrameStructures(frameB, {
|
||||
...frameB,
|
||||
fields: [
|
||||
field0,
|
||||
{
|
||||
...field1,
|
||||
type: FieldType.trace, // Change the type
|
||||
},
|
||||
],
|
||||
})
|
||||
).toBeFalsy();
|
||||
});
|
||||
|
||||
it('full copy of config will not change structure', () => {
|
||||
expect(
|
||||
compareDataFrameStructures(frameB, {
|
||||
...frameB,
|
||||
fields: [
|
||||
field0,
|
||||
{
|
||||
...field1,
|
||||
config: {
|
||||
...field1.config, // no change
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
).toBeTruthy(); // no change
|
||||
});
|
||||
|
||||
it('adding an additional config field', () => {
|
||||
expect(
|
||||
compareDataFrameStructures(frameB, {
|
||||
...frameB,
|
||||
fields: [
|
||||
field0,
|
||||
{
|
||||
...field1,
|
||||
config: {
|
||||
...field1.config,
|
||||
unit: 'rpm',
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
).toBeFalsy();
|
||||
});
|
||||
});
|
67
packages/grafana-data/src/dataframe/frameComparisons.ts
Normal file
67
packages/grafana-data/src/dataframe/frameComparisons.ts
Normal file
@ -0,0 +1,67 @@
|
||||
import { DataFrame } from '../types/dataFrame';
|
||||
|
||||
/**
|
||||
* Returns true if both frames have the same list of fields and configs.
|
||||
* Field may have diferent names, labels and values but share the same structure
|
||||
*
|
||||
* To compare multiple frames use:
|
||||
* ```
|
||||
* areArraysEqual(a, b, framesHaveSameStructure);
|
||||
* ```
|
||||
* NOTE: this does a shallow check on the FieldConfig properties, when using the query
|
||||
* editor, this should be sufficient, however if applicaitons are mutating properties
|
||||
* deep in the FieldConfig this will not recognize a change
|
||||
*
|
||||
* @beta
|
||||
*/
|
||||
export function compareDataFrameStructures(a: DataFrame, b: DataFrame): boolean {
|
||||
if (a === b) {
|
||||
return true;
|
||||
}
|
||||
if (a?.fields?.length !== b?.fields?.length) {
|
||||
return false;
|
||||
}
|
||||
for (let i = 0; i < a.fields.length; i++) {
|
||||
const fA = a.fields[i];
|
||||
const fB = b.fields[i];
|
||||
if (fA.type !== fB.type) {
|
||||
return false;
|
||||
}
|
||||
const cfgA = fA.config as any;
|
||||
const cfgB = fB.config as any;
|
||||
|
||||
const keys = Object.keys(cfgA);
|
||||
if (keys.length !== Object.keys(cfgB).length) {
|
||||
return false;
|
||||
}
|
||||
for (const key of keys) {
|
||||
if (!cfgB.hasOwnProperty(key)) {
|
||||
return false;
|
||||
}
|
||||
if (cfgA[key] !== cfgB[key]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if all values in two arrays match the compare funciton
|
||||
*
|
||||
* @beta
|
||||
*/
|
||||
export function compareArrayValues<T>(a: T[], b: T[], cmp: (a: T, b: T) => boolean) {
|
||||
if (a === b) {
|
||||
return true;
|
||||
}
|
||||
if (a?.length !== b?.length) {
|
||||
return false;
|
||||
}
|
||||
for (let i = 0; i < a.length; i++) {
|
||||
if (!cmp(a[i], b[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
@ -6,3 +6,4 @@ export * from './processDataFrame';
|
||||
export * from './dimensions';
|
||||
export * from './ArrowDataFrame';
|
||||
export * from './ArrayDataFrame';
|
||||
export * from './frameComparisons';
|
||||
|
@ -43,6 +43,5 @@ export const setGrafanaLiveSrv = (instance: GrafanaLiveSrv) => {
|
||||
* server side events and streams
|
||||
*
|
||||
* @alpha -- experimental
|
||||
* @public
|
||||
*/
|
||||
export const getGrafanaLiveSrv = (): GrafanaLiveSrv => singletonInstance;
|
||||
|
Loading…
Reference in New Issue
Block a user