Skip to content

Commit

Permalink
wip/poc
Browse files Browse the repository at this point in the history
  • Loading branch information
ryantxu committed May 24, 2019
1 parent bc3a718 commit 4bef7c0
Show file tree
Hide file tree
Showing 2 changed files with 141 additions and 0 deletions.
40 changes: 40 additions & 0 deletions packages/grafana-ui/src/utils/seriesDataFacade.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { FieldType, SeriesData } from '../types/data';
import { DateTime } from './moment_wrapper';
import { FacadeDefinition, getSeriesDataFacade } from './seriesDataFacade';

interface MySpecialObject {
time: DateTime;
name: string;
value: number;
}

const objectFacadDef: FacadeDefinition<MySpecialObject> = {
fields: [
{ name: 'time', type: FieldType.time },
{ name: 'name', type: FieldType.string },
{ name: 'value', type: FieldType.number },
],
};

describe('seriesDataFacade', () => {
it('converts series to somethign like an object', () => {
const series: SeriesData = {
fields: [
{ name: 'time', type: FieldType.time },
{ name: 'name', type: FieldType.string },
{ name: 'value', type: FieldType.number },
{ name: 'aaa', type: FieldType.string },
{ name: 'bbb', type: FieldType.other },
],
rows: [[1, 'First', 1.23, 'A', { b: 1 }], [2, 'Second', 2.34, 'B', { b: 2 }], [3, 'Third', 3.45, 'C', { b: 3 }]],
};

const iter = getSeriesDataFacade(series, objectFacadDef);
const names: string[] = [];
while (iter.hasNext()) {
const v = iter.next();
names.push(v.name);
}
expect(names).toEqual(['First', 'Second', 'Third']);
});
});
101 changes: 101 additions & 0 deletions packages/grafana-ui/src/utils/seriesDataFacade.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import { SeriesData, Field } from '../types/data';
import { KeyValue } from '../types/index';

export interface SeriesFacadeIterator<T> {
value: T; // object that behaves like T

next: () => T;
getRowData: () => any[];
getRowIndex: () => number;
getSeriesFields: () => Field[];
getAdditionalFields: () => Field[];
getAdditionalValues: () => any[];
}

export interface FacadeDefinition<T> {
fields: Field[];
}

export function getSeriesDataFacade<T>(series: SeriesData, facade: FacadeDefinition<T>) {
const aditionalFields: Field[] = [];
const aditionalIndicies: number[] = [];
let index = 0;
let row = series.rows[index];

const byName: KeyValue<UsedFieldInfo> = {};
for (const f of facade.fields) {
byName[f.name] = {
found: false,
field: f,
};
}

const value = ({} as unknown) as T;
for (let i = 0; i < series.fields.length; i++) {
const field = series.fields[i];
if (byName[field.name]) {
if (byName[field.name].field.type !== field.type) {
throw new Error('type mismatch????');
}
byName[field.name].found = true;
Object.defineProperty(value, field.name, {
get: () => {
if (!row) {
return undefined;
}
return row[i];
},
});
} else {
aditionalFields.push(field);
aditionalIndicies.push(index);
}
}

// abort if we don't have the same fields
for (const f of Object.values(byName)) {
if (!f.found) {
throw new Error('Missing field: ' + f.field.name);
}
}

return {
value: series.rows.length ? value : undefined,

next: () => {
row = series.rows[index++];
return value;
},

hasNext: () => {
return index < series.rows.length;
},

getRowData: () => {
return series.rows[index];
},

getRowIndex: () => {
return index;
},

getSeriesFields: () => {
return series.fields;
},

getAdditionalFields: () => {
return aditionalFields;
},

getAdditionalValues: () => {
return aditionalIndicies.map(idx => {
return row ? row[idx] : undefined;
});
},
};
}

interface UsedFieldInfo {
field: Field;
found: boolean;
}

0 comments on commit 4bef7c0

Please sign in to comment.