Chore: Remove the deprecated Vector type (#83469)

pull/81439/head
Ryan McKinley 1 year ago committed by GitHub
parent 5c60f4d468
commit de75813d8d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 35
      .betterer.results
  2. 6
      packages/grafana-data/src/dataframe/MutableDataFrame.ts
  3. 4
      packages/grafana-data/src/index.ts
  4. 4
      packages/grafana-data/src/transformations/fieldReducer.test.ts
  5. 9
      packages/grafana-data/src/types/dataFrame.ts
  6. 79
      packages/grafana-data/src/types/vector.ts
  7. 27
      packages/grafana-data/src/vector/AppendedVectors.test.ts
  8. 79
      packages/grafana-data/src/vector/AppendedVectors.ts
  9. 45
      packages/grafana-data/src/vector/ArrayVector.test.ts
  10. 46
      packages/grafana-data/src/vector/ArrayVector.ts
  11. 14
      packages/grafana-data/src/vector/AsNumberVector.ts
  12. 24
      packages/grafana-data/src/vector/BinaryOperationVector.test.ts
  13. 18
      packages/grafana-data/src/vector/BinaryOperationVector.ts
  14. 24
      packages/grafana-data/src/vector/CircularVector.ts
  15. 18
      packages/grafana-data/src/vector/ConstantVector.test.ts
  16. 10
      packages/grafana-data/src/vector/ConstantVector.ts
  17. 14
      packages/grafana-data/src/vector/FormattedVector.ts
  18. 14
      packages/grafana-data/src/vector/FunctionalVector.ts
  19. 36
      packages/grafana-data/src/vector/IndexVector.ts
  20. 14
      packages/grafana-data/src/vector/SortedVector.test.ts
  21. 39
      packages/grafana-data/src/vector/SortedVector.ts
  22. 11
      packages/grafana-data/src/vector/index.ts
  23. 10
      packages/grafana-data/src/vector/vectorToArray.ts
  24. 4
      public/app/plugins/datasource/loki/makeTableFrames.ts
  25. 10
      public/app/plugins/datasource/loki/sortDataFrame.ts
  26. 14
      public/app/plugins/panel/datagrid/utils.test.ts
  27. 13
      public/app/plugins/panel/timeseries/utils.ts

@ -33,14 +33,10 @@ exports[`better eslint`] = {
[0, 0, 0, "Unexpected any. Specify a different type.", "5"],
[0, 0, 0, "Unexpected any. Specify a different type.", "6"],
[0, 0, 0, "Unexpected any. Specify a different type.", "7"],
[0, 0, 0, "Unexpected any. Specify a different type.", "8"],
[0, 0, 0, "Do not use any type assertions.", "8"],
[0, 0, 0, "Unexpected any. Specify a different type.", "9"],
[0, 0, 0, "Do not use any type assertions.", "10"],
[0, 0, 0, "Unexpected any. Specify a different type.", "11"],
[0, 0, 0, "Do not use any type assertions.", "12"],
[0, 0, 0, "Unexpected any. Specify a different type.", "13"],
[0, 0, 0, "Unexpected any. Specify a different type.", "14"],
[0, 0, 0, "Do not use any type assertions.", "15"]
[0, 0, 0, "Do not use any type assertions.", "11"]
],
"packages/grafana-data/src/dataframe/StreamingDataFrame.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"],
@ -369,11 +365,6 @@ exports[`better eslint`] = {
"packages/grafana-data/src/types/variables.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
],
"packages/grafana-data/src/types/vector.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],
[0, 0, 0, "Unexpected any. Specify a different type.", "2"]
],
"packages/grafana-data/src/utils/OptionsUIBuilders.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],
@ -448,25 +439,9 @@ exports[`better eslint`] = {
[0, 0, 0, "Unexpected any. Specify a different type.", "3"],
[0, 0, 0, "Unexpected any. Specify a different type.", "4"]
],
"packages/grafana-data/src/vector/AppendedVectors.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
[0, 0, 0, "Do not use any type assertions.", "1"],
[0, 0, 0, "Do not use any type assertions.", "2"]
],
"packages/grafana-data/src/vector/ArrayVector.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],
[0, 0, 0, "Unexpected any. Specify a different type.", "2"]
],
"packages/grafana-data/src/vector/CircularVector.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
],
"packages/grafana-data/src/vector/ConstantVector.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
],
"packages/grafana-data/src/vector/FormattedVector.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
],
"packages/grafana-data/src/vector/FunctionalVector.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],
@ -476,11 +451,7 @@ exports[`better eslint`] = {
[0, 0, 0, "Unexpected any. Specify a different type.", "5"],
[0, 0, 0, "Unexpected any. Specify a different type.", "6"],
[0, 0, 0, "Unexpected any. Specify a different type.", "7"],
[0, 0, 0, "Unexpected any. Specify a different type.", "8"],
[0, 0, 0, "Unexpected any. Specify a different type.", "9"]
],
"packages/grafana-data/src/vector/SortedVector.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
[0, 0, 0, "Unexpected any. Specify a different type.", "8"]
],
"packages/grafana-data/test/__mocks__/pluginMocks.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]

@ -11,7 +11,7 @@ import { guessFieldTypeFromValue, guessFieldTypeForField, toDataFrameDTO } from
export type MutableField<T = any> = Field<T>;
/** @deprecated */
type MutableVectorCreator = (buffer?: any[]) => any[];
type MutableVectorCreator = (buffer?: unknown[]) => unknown[];
export const MISSING_VALUE = undefined; // Treated as connected in new graph panel
@ -243,7 +243,7 @@ export class MutableDataFrame<T = any> extends FunctionalVector<T> implements Da
throw new Error('Unable to set value beyond current length');
}
const obj = (value as any) || {};
const obj = (value as Record<string, unknown>) || {};
for (const field of this.fields) {
field.values[index] = obj[field.name];
}
@ -253,7 +253,7 @@ export class MutableDataFrame<T = any> extends FunctionalVector<T> implements Da
* Get an object with a property for each field in the DataFrame
*/
get(idx: number): T {
const v: any = {};
const v: Record<string, unknown> = {};
for (const field of this.fields) {
v[field.name] = field.values[idx];
}

@ -5,7 +5,6 @@
*/
export * from './utils';
export * from './types';
export * from './vector';
export * from './dataframe';
export * from './transformations';
export * from './datetime';
@ -44,3 +43,6 @@ export {
export { usePluginContext } from './context/plugins/usePluginContext';
export { isDataSourcePluginContext } from './context/plugins/guards';
export { getLinksSupplier } from './field/fieldOverrides';
// deprecated
export { CircularVector } from './vector/CircularVector';

@ -1,7 +1,7 @@
import { difference } from 'lodash';
import { createDataFrame, guessFieldTypeFromValue } from '../dataframe/processDataFrame';
import { Field, FieldType, NullValueMode, Vector } from '../types/index';
import { Field, FieldType, NullValueMode } from '../types/index';
import { fieldReducers, ReducerID, reduceField, defaultCalcs } from './fieldReducer';
@ -65,7 +65,7 @@ describe('Stats Calculators', () => {
it('should handle undefined field data without crashing', () => {
const stats = reduceField({
field: { name: 'a', values: undefined as unknown as Vector, config: {}, type: FieldType.number },
field: { name: 'a', values: undefined as unknown as unknown[], config: {}, type: FieldType.number },
reducers: [ReducerID.first, ReducerID.last, ReducerID.mean, ReducerID.count],
});

@ -5,7 +5,6 @@ import { DecimalCount, DisplayProcessor, DisplayValue, DisplayValueAlignmentFact
import { FieldColor } from './fieldColor';
import { ThresholdsConfig } from './thresholds';
import { ValueMapping } from './valueMapping';
import { Vector } from './vector';
/** @public */
export enum FieldType {
@ -133,7 +132,7 @@ export interface ValueLinkConfig {
valueRowIndex?: number;
}
export interface Field<T = any, V = Vector<T>> {
export interface Field<T = any> {
/**
* Name of the field (column)
*/
@ -149,10 +148,8 @@ export interface Field<T = any, V = Vector<T>> {
/**
* The raw field values
* In Grafana 10, this accepts both simple arrays and the Vector interface
* In Grafana 11, the Vector interface will be removed
*/
values: V | T[];
values: T[];
/**
* When type === FieldType.Time, this can optionally store
@ -264,7 +261,7 @@ export interface FieldDTO<T = any> {
name: string; // The column name
type?: FieldType;
config?: FieldConfig;
values?: Vector<T> | T[]; // toJSON will always be T[], input could be either
values?: T[];
labels?: Labels;
}

@ -53,82 +53,3 @@ export function patchArrayVectorProrotypeMethods() {
}
//this function call is intentional
patchArrayVectorProrotypeMethods();
/** @deprecated use a simple Array<T> */
export interface Vector<T = any> extends Array<T> {
length: number;
/**
* Access the value by index (Like an array)
*
* @deprecated use a simple Array<T>
*/
get(index: number): T;
/**
* Set a value
*
* @deprecated use a simple Array<T>
*/
set: (index: number, value: T) => void;
/**
* Adds the value to the vector
* Same as Array.push()
*
* @deprecated use a simple Array<T>
*/
add: (value: T) => void;
/**
* Get the results as an array.
*
* @deprecated use a simple Array<T>
*/
toArray(): T[];
}
/**
* Apache arrow vectors are Read/Write
*
* @deprecated -- this is now part of the base Vector interface
*/
export interface ReadWriteVector<T = any> extends Vector<T> {}
/**
* Vector with standard manipulation functions
*
* @deprecated -- this is now part of the base Vector interface
*/
export interface MutableVector<T = any> extends ReadWriteVector<T> {}
/**
* This is an extremely inefficient Vector wrapper that allows vectors to
* be treated as arrays. We should avoid using this wrapper, but it is helpful
* for a clean migration to arrays
*
* @deprecated
*/
export function makeArrayIndexableVector<T extends Vector>(v: T): T {
return new Proxy<T>(v, {
get(target: Vector, property: string, receiver: Vector) {
if (typeof property !== 'symbol') {
const idx = +property;
if (String(idx) === property) {
return target.get(idx);
}
}
return Reflect.get(target, property, receiver);
},
set(target: Vector, property: string, value: unknown, receiver: Vector) {
if (typeof property !== 'symbol') {
const idx = +property;
if (String(idx) === property) {
target.set(idx, value);
return true;
}
}
return Reflect.set(target, property, value, receiver);
},
});
}

@ -1,27 +0,0 @@
import { AppendedVectors } from './AppendedVectors';
import { ArrayVector } from './ArrayVector';
describe('Check Appending Vector', () => {
it('should transparently join them', () => {
jest.spyOn(console, 'warn').mockImplementation();
const appended = new AppendedVectors();
appended.append(new ArrayVector([1, 2, 3]));
appended.append(new ArrayVector([4, 5, 6]));
appended.append(new ArrayVector([7, 8, 9]));
expect(appended.length).toEqual(9);
expect(appended[0]).toEqual(1);
expect(appended[1]).toEqual(2);
expect(appended[100]).toEqual(undefined);
appended.setLength(5);
expect(appended.length).toEqual(5);
appended.append(new ArrayVector(['a', 'b', 'c']));
expect(appended.length).toEqual(8);
expect(appended.toArray()).toEqual([1, 2, 3, 4, 5, 'a', 'b', 'c']);
appended.setLength(2);
appended.setLength(6);
appended.append(new ArrayVector(['x', 'y', 'z']));
expect(appended.toArray()).toEqual([1, 2, undefined, undefined, undefined, undefined, 'x', 'y', 'z']);
});
});

@ -1,79 +0,0 @@
import { Vector, makeArrayIndexableVector } from '../types/vector';
import { FunctionalVector } from './FunctionalVector';
import { vectorToArray } from './vectorToArray';
interface AppendedVectorInfo<T> {
start: number;
end: number;
values: Vector<T>;
}
/**
* This may be more trouble than it is worth. This trades some computation time for
* RAM -- rather than allocate a new array the size of all previous arrays, this just
* points the correct index to their original array values
*
* @deprecated use a simple Arrays. NOTE this is not used in grafana core
*/
export class AppendedVectors<T = any> extends FunctionalVector<T> {
length = 0;
source: Array<AppendedVectorInfo<T>> = [];
constructor(startAt = 0) {
super();
this.length = startAt;
return makeArrayIndexableVector(this);
}
/**
* Make the vector look like it is this long
*/
setLength(length: number) {
if (length > this.length) {
// make the vector longer (filling with undefined)
this.length = length;
} else if (length < this.length) {
// make the array shorter
const sources: Array<AppendedVectorInfo<T>> = [];
for (const src of this.source) {
sources.push(src);
if (src.end > length) {
src.end = length;
break;
}
}
this.source = sources;
this.length = length;
}
}
append(v: Vector<T>): AppendedVectorInfo<T> {
const info = {
start: this.length,
end: this.length + v.length,
values: v,
};
this.length = info.end;
this.source.push(info);
return info;
}
get(index: number): T {
for (let i = 0; i < this.source.length; i++) {
const src = this.source[i];
if (index >= src.start && index < src.end) {
return src.values[index - src.start];
}
}
return undefined as unknown as T;
}
toArray(): T[] {
return vectorToArray(this);
}
toJSON(): T[] {
return vectorToArray(this);
}
}

@ -1,45 +0,0 @@
import { Field, FieldType } from '../types';
import { ArrayVector } from './ArrayVector';
describe('ArrayVector', () => {
beforeEach(() => {
jest.spyOn(console, 'warn').mockImplementation();
});
it('should init 150k with 65k Array.push() chonking', () => {
const arr = Array.from({ length: 150e3 }, (v, i) => i);
const av = new ArrayVector(arr);
expect(av.toArray()).toEqual(arr);
});
it('should support add and push', () => {
const av = new ArrayVector<number>();
av.add(1);
av.push(2);
av.push(3, 4);
expect(av.toArray()).toEqual([1, 2, 3, 4]);
});
it('typescript should not re-define the ArrayVector<T> based on input to the constructor', () => {
const field: Field<number> = {
name: 'test',
config: {},
type: FieldType.number,
values: new ArrayVector(), // this defaults to `new ArrayVector<any>()`
};
expect(field).toBeDefined();
// Before collapsing Vector, ReadWriteVector, and MutableVector these all worked fine
field.values = new ArrayVector();
field.values = new ArrayVector(undefined);
field.values = new ArrayVector([1, 2, 3]);
field.values = new ArrayVector([]);
field.values = new ArrayVector([1, undefined]);
field.values = new ArrayVector([null]);
field.values = new ArrayVector(['a', 'b', 'c']);
expect(field.values.length).toBe(3);
});
});

@ -1,46 +0,0 @@
const notice = 'ArrayVector is deprecated and will be removed in Grafana 11. Please use plain arrays for field.values.';
let notified = false;
/**
* @public
*
* @deprecated use a simple Array<T>
*/
export class ArrayVector<T = any> extends Array<T> {
get buffer() {
return this;
}
set buffer(values: any[]) {
this.length = 0;
const len = values?.length;
if (len) {
let chonkSize = 65e3;
let numChonks = Math.ceil(len / chonkSize);
for (let chonkIdx = 0; chonkIdx < numChonks; chonkIdx++) {
this.push.apply(this, values.slice(chonkIdx * chonkSize, (chonkIdx + 1) * chonkSize));
}
}
}
/**
* This any type is here to make the change type changes in v10 non breaking for plugins.
* Before you could technically assign field.values any typed ArrayVector no matter what the Field<T> T type was.
*/
constructor(buffer?: any[]) {
super();
this.buffer = buffer ?? [];
if (!notified) {
console.warn(notice);
notified = true;
}
}
toJSON(): T[] {
return [...this]; // copy to avoid circular reference (only for jest)
}
}

@ -1,14 +0,0 @@
import { Vector } from '../types';
/**
* This will force all values to be numbers
*
* @public
* @deprecated use a simple Arrays. NOTE: Not used in grafana core
*/
export class AsNumberVector extends Array<number> {
constructor(field: Vector) {
super();
return field.map((v) => +v);
}
}

@ -1,24 +0,0 @@
import { binaryOperators, BinaryOperationID } from '../utils/binaryOperators';
import { ArrayVector } from './ArrayVector';
import { BinaryOperationVector } from './BinaryOperationVector';
import { ConstantVector } from './ConstantVector';
describe('ScaledVector', () => {
it('should support multiply operations', () => {
jest.spyOn(console, 'warn').mockImplementation();
const source = new ArrayVector([1, 2, 3, 4]);
const scale = 2.456;
const operation = binaryOperators.get(BinaryOperationID.Multiply).operation;
const v = new BinaryOperationVector(source, new ConstantVector(scale, source.length), operation);
expect(v.length).toEqual(source.length);
// Accessed with getters
for (let i = 0; i < 4; i++) {
expect(v.get(i)).toEqual(source.get(i) * scale);
}
// Accessed with array index
for (let i = 0; i < 4; i++) {
expect(v[i]).toEqual(source[i] * scale);
}
});
});

@ -1,18 +0,0 @@
import { Vector } from '../types/vector';
import { BinaryOperation } from '../utils/binaryOperators';
/**
* @public
* @deprecated use a simple Arrays. NOTE: Not used in grafana core
*/
export class BinaryOperationVector extends Array<number> {
constructor(left: Vector<number>, right: Vector<number>, operation: BinaryOperation) {
super();
const arr = new Array(left.length);
for (let i = 0; i < arr.length; i++) {
arr[i] = operation(left[i], right[i]);
}
return arr;
}
}

@ -1,5 +1,3 @@
import { makeArrayIndexableVector } from '../types';
import { FunctionalVector } from './FunctionalVector';
interface CircularOptions<T> {
@ -36,7 +34,27 @@ export class CircularVector<T = any> extends FunctionalVector<T> {
if (options.capacity) {
this.setCapacity(options.capacity);
}
return makeArrayIndexableVector(this);
return new Proxy(this, {
get(target: CircularVector<T>, property: string, receiver: CircularVector<T>) {
if (typeof property !== 'symbol') {
const idx = +property;
if (String(idx) === property) {
return target.get(idx);
}
}
return Reflect.get(target, property, receiver);
},
set(target: CircularVector<T>, property: string, value: T, receiver: CircularVector<T>) {
if (typeof property !== 'symbol') {
const idx = +property;
if (String(idx) === property) {
target.set(idx, value);
return true;
}
}
return Reflect.set(target, property, value, receiver);
},
});
}
/**

@ -1,18 +0,0 @@
import { ConstantVector } from './ConstantVector';
describe('ConstantVector', () => {
it('should support constant values', () => {
const value = 3.5;
const v = new ConstantVector(value, 7);
expect(v.length).toEqual(7);
expect(v.get(0)).toEqual(value);
expect(v.get(1)).toEqual(value);
// Now check all of them
for (let i = 0; i < 7; i++) {
expect(v.get(i)).toEqual(value);
expect(v[i]).toEqual(value);
}
});
});

@ -1,10 +0,0 @@
/**
* @public
* @deprecated use a simple Arrays. NOTE: Not used in grafana core.
*/
export class ConstantVector<T = any> extends Array<T> {
constructor(value: T, len: number) {
super();
return new Array<T>(len).fill(value);
}
}

@ -1,14 +0,0 @@
import { DisplayProcessor } from '../types';
import { Vector } from '../types/vector';
import { formattedValueToString } from '../valueFormats';
/**
* @public
* @deprecated use a simple Arrays. NOTE: not used in grafana core.
*/
export class FormattedVector<T = any> extends Array<string> {
constructor(source: Vector<T>, formatter: DisplayProcessor) {
super();
return source.map((v) => formattedValueToString(formatter(v)));
}
}

@ -1,12 +1,8 @@
import { Vector } from '../types';
import { vectorToArray } from './vectorToArray';
/**
* @public
* @deprecated use a simple Arrays
*/
export abstract class FunctionalVector<T = any> implements Vector<T> {
export abstract class FunctionalVector<T = unknown> {
abstract get length(): number;
abstract get(index: number): T;
@ -55,7 +51,11 @@ export abstract class FunctionalVector<T = any> implements Vector<T> {
}
toArray(): T[] {
return vectorToArray(this);
const arr = new Array<T>(this.length);
for (let i = 0; i < this.length; i++) {
arr[i] = this.get(i);
}
return arr;
}
join(separator?: string | undefined): string {
@ -183,7 +183,7 @@ const emptyarray: any[] = [];
*
* @deprecated use a simple Arrays
*/
export function vectorator<T>(vector: Vector<T>) {
function vectorator<T>(vector: FunctionalVector<T>) {
return {
*[Symbol.iterator]() {
for (let i = 0; i < vector.length; i++) {

@ -1,36 +0,0 @@
import { Field, FieldType } from '../types';
/**
* IndexVector is a simple vector implementation that returns the index value
* for each element in the vector. It is functionally equivolant a vector backed
* by an array with values: `[0,1,2,...,length-1]`
*
* @deprecated use a simple Arrays. NOTE: not used in grafana core
*/
export class IndexVector extends Array<number> {
constructor(len: number) {
super();
const arr = new Array(len);
for (let i = 0; i < len; i++) {
arr[i] = i;
}
return arr;
}
/**
* Returns a field representing the range [0 ... length-1]
*
* @deprecated
*/
static newField(len: number): Field<number> {
return {
name: '',
values: new IndexVector(len),
type: FieldType.number,
config: {
min: 0,
max: len - 1,
},
};
}
}

@ -1,14 +0,0 @@
import { ArrayVector } from './ArrayVector';
import { SortedVector } from './SortedVector';
describe('SortedVector', () => {
it('Should support sorting', () => {
jest.spyOn(console, 'warn').mockImplementation();
const values = new ArrayVector([1, 5, 2, 4]);
const sorted = new SortedVector(values, [0, 2, 3, 1]);
expect(sorted.toArray()).toEqual([1, 2, 4, 5]);
// The proxy should still be an instance of SortedVector (used in timeseries)
expect(sorted instanceof SortedVector).toBeTruthy();
});
});

@ -1,39 +0,0 @@
import { makeArrayIndexableVector, Vector } from '../types/vector';
import { FunctionalVector } from './FunctionalVector';
import { vectorToArray } from './vectorToArray';
/**
* Values are returned in the order defined by the input parameter
*
* @deprecated use a simple Arrays
*/
export class SortedVector<T = any> extends FunctionalVector<T> {
constructor(
private source: Vector<T>,
private order: number[]
) {
super();
return makeArrayIndexableVector(this);
}
get length(): number {
return this.source.length;
}
get(index: number): T {
return this.source.get(this.order[index]);
}
toArray(): T[] {
return vectorToArray(this);
}
toJSON(): T[] {
return vectorToArray(this);
}
getOrderArray(): number[] {
return this.order;
}
}

@ -1,11 +0,0 @@
export * from './AppendedVectors';
export * from './ArrayVector';
export * from './CircularVector';
export * from './ConstantVector';
export * from './BinaryOperationVector';
export * from './SortedVector';
export * from './FormattedVector';
export * from './IndexVector';
export * from './AsNumberVector';
export { vectorator } from './FunctionalVector';

@ -1,10 +0,0 @@
import { Vector } from '../types/vector';
/** @deprecated use a simple Arrays */
export function vectorToArray<T>(v: Vector<T>): T[] {
const arr: T[] = Array(v.length);
for (let i = 0; i < v.length; i++) {
arr[i] = v.get(i);
}
return arr;
}

@ -12,8 +12,8 @@ export function makeTableFrames(instantMetricFrames: DataFrame[]): DataFrame[] {
return Object.entries(framesByRefId).map(([refId, frames]) => makeTableFrame(frames, refId));
}
type NumberField = Field<number, number[]>;
type StringField = Field<string, string[]>;
type NumberField = Field<number>;
type StringField = Field<string>;
function makeTableFrame(instantMetricFrames: DataFrame[], refId: string): DataFrame {
const tableTimeField: NumberField = { name: 'Time', config: {}, values: [], type: FieldType.time };

@ -1,4 +1,4 @@
import { DataFrame, Field, FieldType, SortedVector } from '@grafana/data';
import { DataFrame, Field, FieldType } from '@grafana/data';
export enum SortDirection {
Ascending,
@ -85,10 +85,12 @@ export function sortDataFrameByTime(frame: DataFrame, dir: SortDirection): DataF
...rest,
fields: fields.map((field) => ({
...field,
values: new SortedVector(field.values, index).toArray(),
nanos: field.nanos === undefined ? undefined : new SortedVector(field.nanos, index).toArray(),
values: sorted(field.values, index),
nanos: field.nanos === undefined ? undefined : sorted(field.nanos, index),
})),
};
}
return frame;
function sorted<T>(vals: T[], index: number[]): T[] {
return vals.map((_, idx) => vals[index[idx]]);
}

@ -1,4 +1,4 @@
import { ArrayVector, DataFrame, FieldType } from '@grafana/data';
import { DataFrame, FieldType } from '@grafana/data';
import { clearCellsFromRangeSelection, deleteRows } from './utils';
@ -14,19 +14,19 @@ describe('when deleting rows', () => {
{
name: 'test1',
type: FieldType.string,
values: new ArrayVector(['a', 'b', 'c', 'd', 'e']),
values: ['a', 'b', 'c', 'd', 'e'],
config: {},
},
{
name: 'test2',
type: FieldType.number,
values: new ArrayVector([1, 2, 3, 4, 5]),
values: [1, 2, 3, 4, 5],
config: {},
},
{
name: 'test3',
type: FieldType.string,
values: new ArrayVector(['a', 'b', 'c', 'd', 'e']),
values: ['a', 'b', 'c', 'd', 'e'],
config: {},
},
],
@ -98,19 +98,19 @@ describe('when clearing cells from range selection', () => {
{
name: 'test1',
type: FieldType.string,
values: new ArrayVector(['a', 'b', 'c', 'd', 'e']),
values: ['a', 'b', 'c', 'd', 'e'],
config: {},
},
{
name: 'test2',
type: FieldType.number,
values: new ArrayVector([1, 2, 3, 4, 5]),
values: [1, 2, 3, 4, 5],
config: {},
},
{
name: 'test3',
type: FieldType.string,
values: new ArrayVector(['a', 'b', 'c', 'd', 'e']),
values: ['a', 'b', 'c', 'd', 'e'],
config: {},
},
],

@ -8,7 +8,6 @@ import {
DataLinkPostProcessor,
InterpolateFunction,
isBooleanUnit,
SortedVector,
TimeRange,
cacheFieldDisplayNames,
} from '@grafana/data';
@ -279,20 +278,10 @@ export function regenerateLinksSupplier(
return;
}
/* check if field has sortedVector values
if it does, sort all string fields in the original frame by the order array already used for the field
otherwise just attach the fields to the temporary frame used to get the links
*/
const tempFields: Field[] = [];
for (const frameField of frames[field.state?.origin?.frameIndex].fields) {
if (frameField.type === FieldType.string) {
if (field.values instanceof SortedVector) {
const copiedField = { ...frameField };
copiedField.values = new SortedVector(frameField.values, field.values.getOrderArray());
tempFields.push(copiedField);
} else {
tempFields.push(frameField);
}
tempFields.push(frameField);
}
}

Loading…
Cancel
Save