Skip to content

Commit

Permalink
[v9.3.x] TimeseriesPanel: Preserve string fields for data link interp…
Browse files Browse the repository at this point in the history
…olation (grafana#59869)

TimeseriesPanel: Preserve string fields for data link interpolation (grafana#58424)

* TimeseriesPanel: Preserve string fields for data link interpolation

* clean code

* Modify tests so that string fields are allowed only when a valid time/number dataframe exists

* performance mods

* fix wrong length

* remove console.log

* Check if aligned dataframe has links

(cherry picked from commit 0da7720)

Co-authored-by: Victor Marin <36818606+mdvictor@users.noreply.github.com>
  • Loading branch information
2 people authored and GuaYounesPW committed Feb 8, 2023
1 parent a1911bb commit ae7506a
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 12 deletions.
4 changes: 4 additions & 0 deletions packages/grafana-data/src/vector/SortedVector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,8 @@ export class SortedVector<T = any> implements Vector<T> {
toJSON(): T[] {
return vectorToArray(this);
}

getOrderArray(): number[] {
return this.order;
}
}
18 changes: 7 additions & 11 deletions public/app/plugins/panel/timeseries/TimeSeriesPanel.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { useMemo } from 'react';

import { Field, PanelProps, getLinksSupplier } from '@grafana/data';
import { Field, PanelProps } from '@grafana/data';
import { PanelDataErrorView } from '@grafana/runtime';
import { TooltipDisplayMode } from '@grafana/schema';
import { usePanelContext, TimeSeries, TooltipPlugin, ZoomPlugin, KeyboardPlugin } from '@grafana/ui';
Expand All @@ -14,7 +14,7 @@ import { ExemplarsPlugin } from './plugins/ExemplarsPlugin';
import { OutsideRangePlugin } from './plugins/OutsideRangePlugin';
import { ThresholdControlsPlugin } from './plugins/ThresholdControlsPlugin';
import { TimeSeriesOptions } from './types';
import { getTimezones, prepareGraphableFields } from './utils';
import { getTimezones, prepareGraphableFields, regenerateLinksSupplier } from './utils';

interface TimeSeriesPanelProps extends PanelProps<TimeSeriesOptions> {}

Expand Down Expand Up @@ -65,15 +65,11 @@ export const TimeSeriesPanel: React.FC<TimeSeriesPanelProps> = ({
options={options}
>
{(config, alignedDataFrame) => {
alignedDataFrame.fields.forEach((field) => {
field.getLinks = getLinksSupplier(
alignedDataFrame,
field,
field.state!.scopedVars!,
replaceVariables,
timeZone
);
});
if (
alignedDataFrame.fields.filter((f) => f.config.links !== undefined && f.config.links.length > 0).length > 0
) {
alignedDataFrame = regenerateLinksSupplier(alignedDataFrame, frames, replaceVariables, timeZone);
}

return (
<>
Expand Down
2 changes: 1 addition & 1 deletion public/app/plugins/panel/timeseries/utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ describe('prepare timeseries graph', () => {
const frames = prepareGraphableFields(input, createTheme());
const out = frames![0];

expect(out.fields.map((f) => f.name)).toEqual(['a', 'c', 'd']);
expect(out.fields.map((f) => f.name)).toEqual(['a', 'b', 'c', 'd']);

const field = out.fields.find((f) => f.name === 'c');
expect(field?.display).toBeDefined();
Expand Down
54 changes: 54 additions & 0 deletions public/app/plugins/panel/timeseries/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@ import {
Field,
FieldType,
getDisplayProcessor,
getLinksSupplier,
GrafanaTheme2,
InterpolateFunction,
isBooleanUnit,
SortedVector,
TimeRange,
} from '@grafana/data';
import { GraphFieldConfig, LineInterpolation } from '@grafana/schema';
Expand Down Expand Up @@ -60,6 +63,14 @@ export function prepareGraphableFields(
),
};

fields.push(copy);
break; // ok
case FieldType.string:
copy = {
...field,
values: new ArrayVector(field.values.toArray()),
};

fields.push(copy);
break; // ok
case FieldType.boolean:
Expand Down Expand Up @@ -123,3 +134,46 @@ export function getTimezones(timezones: string[] | undefined, defaultTimezone: s
}
return timezones.map((v) => (v?.length ? v : defaultTimezone));
}

export function regenerateLinksSupplier(
alignedDataFrame: DataFrame,
frames: DataFrame[],
replaceVariables: InterpolateFunction,
timeZone: string
): DataFrame {
alignedDataFrame.fields.forEach((field) => {
const frameIndex = field.state?.origin?.frameIndex;

if (frameIndex === undefined) {
return;
}

const frame = frames[frameIndex];
const tempFields: Field[] = [];

/* 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
*/
for (const frameField of frame.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);
}
}
}

const tempFrame: DataFrame = {
fields: [...alignedDataFrame.fields, ...tempFields],
length: alignedDataFrame.fields.length + tempFields.length,
};

field.getLinks = getLinksSupplier(tempFrame, field, field.state!.scopedVars!, replaceVariables, timeZone);
});

return alignedDataFrame;
}

0 comments on commit ae7506a

Please sign in to comment.