mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Theme: Move displayProcessor & fieldOverrides & visualizations to use new theme model (#33502)
* WIP updating getColorForTheme * Progress * More fixes * Updating more parts * Fixing unit tests * Fixing more tests * Fixing storybook issues * More refactoring * Fixed test
This commit is contained in:
parent
0836e7bde8
commit
017bcc73ba
@ -3,6 +3,7 @@ import { DisplayProcessor, DisplayValue } from '../types/displayValue';
|
||||
import { MappingType, ValueMapping } from '../types/valueMapping';
|
||||
import { FieldConfig, FieldType, ThresholdsMode } from '../types';
|
||||
import { systemDateFormats } from '../datetime';
|
||||
import { createTheme } from '../themes';
|
||||
|
||||
function getDisplayProcessorFromConfig(config: FieldConfig) {
|
||||
return getDisplayProcessor({
|
||||
@ -10,6 +11,7 @@ function getDisplayProcessorFromConfig(config: FieldConfig) {
|
||||
config,
|
||||
type: FieldType.number,
|
||||
},
|
||||
theme: createTheme(),
|
||||
});
|
||||
}
|
||||
|
||||
@ -26,7 +28,7 @@ describe('Process simple display values', () => {
|
||||
// Don't test float values here since the decimal formatting changes
|
||||
const processors = [
|
||||
// Without options, this shortcuts to a much easier implementation
|
||||
getDisplayProcessor({ field: { config: {} } }),
|
||||
getDisplayProcessor({ field: { config: {} }, theme: createTheme() }),
|
||||
|
||||
// Add a simple option that is not used (uses a different base class)
|
||||
getDisplayProcessorFromConfig({ min: 0, max: 100 }),
|
||||
@ -249,6 +251,7 @@ describe('Date display options', () => {
|
||||
unit: 'xyz', // ignore non-date formats
|
||||
},
|
||||
},
|
||||
theme: createTheme(),
|
||||
});
|
||||
expect(processor(0).text).toEqual('1970-01-01 00:00:00');
|
||||
});
|
||||
@ -262,6 +265,7 @@ describe('Date display options', () => {
|
||||
unit: 'dateTimeAsUS', // ignore non-date formats
|
||||
},
|
||||
},
|
||||
theme: createTheme(),
|
||||
});
|
||||
expect(processor(0).text).toEqual('01/01/1970 12:00:00 am');
|
||||
});
|
||||
@ -275,6 +279,7 @@ describe('Date display options', () => {
|
||||
unit: 'time:YYYY', // ignore non-date formats
|
||||
},
|
||||
},
|
||||
theme: createTheme(),
|
||||
});
|
||||
expect(processor(0).text).toEqual('1970');
|
||||
});
|
||||
@ -289,6 +294,7 @@ describe('Date display options', () => {
|
||||
type: FieldType.time,
|
||||
config: {},
|
||||
},
|
||||
theme: createTheme(),
|
||||
});
|
||||
|
||||
expect(processor(0).text).toEqual('1970-01');
|
||||
@ -303,6 +309,7 @@ describe('Date display options', () => {
|
||||
type: FieldType.time,
|
||||
config: {},
|
||||
},
|
||||
theme: createTheme(),
|
||||
});
|
||||
|
||||
expect(processor('2020-08-01T08:48:43.783337Z').text).toEqual('2020-08-01 08:48:43');
|
||||
@ -315,6 +322,7 @@ describe('Date display options', () => {
|
||||
type: FieldType.string,
|
||||
config: { unit: 'string' },
|
||||
},
|
||||
theme: createTheme(),
|
||||
});
|
||||
expect(processor('22.1122334455').text).toEqual('22.1122334455');
|
||||
});
|
||||
@ -325,6 +333,7 @@ describe('Date display options', () => {
|
||||
type: FieldType.string,
|
||||
config: { decimals: 2 },
|
||||
},
|
||||
theme: createTheme(),
|
||||
});
|
||||
expect(processor('22.1122334455').text).toEqual('22.11');
|
||||
});
|
||||
|
@ -3,14 +3,13 @@ import { toString, toNumber as _toNumber, isEmpty, isBoolean } from 'lodash';
|
||||
|
||||
// Types
|
||||
import { Field, FieldType } from '../types/dataFrame';
|
||||
import { GrafanaTheme } from '../types/theme';
|
||||
import { DisplayProcessor, DisplayValue } from '../types/displayValue';
|
||||
import { getValueFormat } from '../valueFormats/valueFormats';
|
||||
import { getMappedValue } from '../utils/valueMappings';
|
||||
import { dateTime } from '../datetime';
|
||||
import { KeyValue, TimeZone } from '../types';
|
||||
import { getScaleCalculator } from './scale';
|
||||
import { getTestTheme } from '../utils/testdata/testTheme';
|
||||
import { GrafanaThemeV2 } from '../themes/types';
|
||||
|
||||
interface DisplayProcessorOptions {
|
||||
field: Partial<Field>;
|
||||
@ -21,7 +20,7 @@ interface DisplayProcessorOptions {
|
||||
/**
|
||||
* Will pick 'dark' if not defined
|
||||
*/
|
||||
theme?: GrafanaTheme;
|
||||
theme: GrafanaThemeV2;
|
||||
}
|
||||
|
||||
// Reasonable units for time
|
||||
@ -43,9 +42,6 @@ export function getDisplayProcessor(options?: DisplayProcessorOptions): DisplayP
|
||||
const { field } = options;
|
||||
const config = field.config ?? {};
|
||||
|
||||
// Theme should be required or we need access to default theme instance from here
|
||||
const theme = options.theme ?? getTestTheme();
|
||||
|
||||
let unit = config.unit;
|
||||
let hasDateUnit = unit && (timeFormats[unit] || unit.startsWith('time:'));
|
||||
|
||||
@ -55,7 +51,7 @@ export function getDisplayProcessor(options?: DisplayProcessorOptions): DisplayP
|
||||
}
|
||||
|
||||
const formatFunc = getValueFormat(unit || 'none');
|
||||
const scaleFunc = getScaleCalculator(field as Field, theme);
|
||||
const scaleFunc = getScaleCalculator(field as Field, options.theme);
|
||||
|
||||
return (value: any) => {
|
||||
const { mappings } = config;
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { createTheme } from '../themes';
|
||||
import { Field, FieldColorModeId, FieldType } from '../types';
|
||||
import { getTestTheme } from '../utils/testdata/testTheme';
|
||||
import { ArrayVector } from '../vector/ArrayVector';
|
||||
import { fieldColorModeRegistry, FieldValueColorCalculator, getFieldSeriesColor } from './fieldColor';
|
||||
|
||||
@ -26,7 +26,7 @@ function getCalculator(options: GetCalcOptions): FieldValueColorCalculator {
|
||||
const field = getTestField(options.mode);
|
||||
const mode = fieldColorModeRegistry.get(options.mode);
|
||||
field.state!.seriesIndex = options.seriesIndex;
|
||||
return mode.getCalculator(field, getTestTheme());
|
||||
return mode.getCalculator(field, createTheme());
|
||||
}
|
||||
|
||||
describe('fieldColorModeRegistry', () => {
|
||||
@ -53,7 +53,7 @@ describe('fieldColorModeRegistry', () => {
|
||||
// last percent 75%
|
||||
field.values = new ArrayVector([0, -10, 5, 10, 2, 5]);
|
||||
|
||||
const color = getFieldSeriesColor(field, getTestTheme());
|
||||
const color = getFieldSeriesColor(field, createTheme());
|
||||
const calcFn = getCalculator({ mode: 'continuous-GrYlRd' });
|
||||
|
||||
expect(color.color).toEqual(calcFn(4, 0.75));
|
||||
@ -66,7 +66,7 @@ describe('getFieldSeriesColor', () => {
|
||||
|
||||
it('When color.seriesBy is last use that to calc series color', () => {
|
||||
field.config.color!.seriesBy = 'last';
|
||||
const color = getFieldSeriesColor(field, getTestTheme());
|
||||
const color = getFieldSeriesColor(field, createTheme());
|
||||
const calcFn = getCalculator({ mode: 'continuous-GrYlRd' });
|
||||
|
||||
// the 4 can be anything, 0.75 comes from 5 being 75% in the range -10 to 10 (see data above)
|
||||
@ -75,7 +75,7 @@ describe('getFieldSeriesColor', () => {
|
||||
|
||||
it('When color.seriesBy is max use that to calc series color', () => {
|
||||
field.config.color!.seriesBy = 'max';
|
||||
const color = getFieldSeriesColor(field, getTestTheme());
|
||||
const color = getFieldSeriesColor(field, createTheme());
|
||||
const calcFn = getCalculator({ mode: 'continuous-GrYlRd' });
|
||||
|
||||
expect(color.color).toEqual(calcFn(10, 1));
|
||||
@ -83,7 +83,7 @@ describe('getFieldSeriesColor', () => {
|
||||
|
||||
it('When color.seriesBy is min use that to calc series color', () => {
|
||||
field.config.color!.seriesBy = 'min';
|
||||
const color = getFieldSeriesColor(field, getTestTheme());
|
||||
const color = getFieldSeriesColor(field, createTheme());
|
||||
const calcFn = getCalculator({ mode: 'continuous-GrYlRd' });
|
||||
|
||||
expect(color.color).toEqual(calcFn(-10, 0));
|
||||
|
@ -1,17 +1,18 @@
|
||||
import { FALLBACK_COLOR, Field, FieldColorModeId, GrafanaTheme, Threshold } from '../types';
|
||||
import { FALLBACK_COLOR, Field, FieldColorModeId, Threshold } from '../types';
|
||||
import { classicColors, getColorForTheme, RegistryItem } from '../utils';
|
||||
import { Registry } from '../utils/Registry';
|
||||
import { interpolateRgbBasis } from 'd3-interpolate';
|
||||
import { fallBackTreshold } from './thresholds';
|
||||
import { getScaleCalculator, ColorScaleValue } from './scale';
|
||||
import { reduceField } from '../transformations/fieldReducer';
|
||||
import { GrafanaThemeV2 } from '../themes/types';
|
||||
|
||||
/** @beta */
|
||||
export type FieldValueColorCalculator = (value: number, percent: number, Threshold?: Threshold) => string;
|
||||
|
||||
/** @beta */
|
||||
export interface FieldColorMode extends RegistryItem {
|
||||
getCalculator: (field: Field, theme: GrafanaTheme) => FieldValueColorCalculator;
|
||||
getCalculator: (field: Field, theme: GrafanaThemeV2) => FieldValueColorCalculator;
|
||||
colors?: string[];
|
||||
isContinuous?: boolean;
|
||||
isByValue?: boolean;
|
||||
@ -34,7 +35,7 @@ export const fieldColorModeRegistry = new Registry<FieldColorMode>(() => {
|
||||
getCalculator: (_field, theme) => {
|
||||
return (_value, _percent, threshold) => {
|
||||
const thresholdSafe = threshold ?? fallBackTreshold;
|
||||
return getColorForTheme(thresholdSafe.color, theme);
|
||||
return getColorForTheme(thresholdSafe.color, theme.v1);
|
||||
};
|
||||
},
|
||||
},
|
||||
@ -166,12 +167,12 @@ export class FieldColorSchemeMode implements FieldColorMode {
|
||||
this.isByValue = options.isByValue;
|
||||
}
|
||||
|
||||
private getColors(theme: GrafanaTheme) {
|
||||
private getColors(theme: GrafanaThemeV2) {
|
||||
if (this.colorCache) {
|
||||
return this.colorCache;
|
||||
}
|
||||
|
||||
this.colorCache = this.colors.map((c) => getColorForTheme(c, theme));
|
||||
this.colorCache = this.colors.map((c) => getColorForTheme(c, theme.v1));
|
||||
return this.colorCache;
|
||||
}
|
||||
|
||||
@ -183,7 +184,7 @@ export class FieldColorSchemeMode implements FieldColorMode {
|
||||
return this.interpolator;
|
||||
}
|
||||
|
||||
getCalculator(field: Field, theme: GrafanaTheme) {
|
||||
getCalculator(field: Field, theme: GrafanaThemeV2) {
|
||||
const colors = this.getColors(theme);
|
||||
|
||||
if (this.isByValue) {
|
||||
@ -221,7 +222,7 @@ export function getFieldColorMode(mode?: FieldColorModeId | string): FieldColorM
|
||||
* Function that will return a series color for any given color mode. If the color mode is a by value color
|
||||
* mode it will use the field.config.color.seriesBy property to figure out which value to use
|
||||
*/
|
||||
export function getFieldSeriesColor(field: Field, theme: GrafanaTheme): ColorScaleValue {
|
||||
export function getFieldSeriesColor(field: Field, theme: GrafanaThemeV2): ColorScaleValue {
|
||||
const mode = getFieldColorModeForField(field);
|
||||
|
||||
if (!mode.isByValue) {
|
||||
@ -240,8 +241,8 @@ export function getFieldSeriesColor(field: Field, theme: GrafanaTheme): ColorSca
|
||||
return scale(value);
|
||||
}
|
||||
|
||||
function getFixedColor(field: Field, theme: GrafanaTheme) {
|
||||
function getFixedColor(field: Field, theme: GrafanaThemeV2) {
|
||||
return () => {
|
||||
return getColorForTheme(field.config.color?.fixedColor ?? FALLBACK_COLOR, theme);
|
||||
return getColorForTheme(field.config.color?.fixedColor ?? FALLBACK_COLOR, theme.v1);
|
||||
};
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ import { toDataFrame } from '../dataframe/processDataFrame';
|
||||
import { ReducerID } from '../transformations/fieldReducer';
|
||||
import { MappingType } from '../types';
|
||||
import { standardFieldConfigEditorRegistry } from './standardFieldConfigEditorRegistry';
|
||||
import { getTestTheme } from '../utils/testdata/testTheme';
|
||||
import { createTheme } from '../themes';
|
||||
|
||||
describe('FieldDisplay', () => {
|
||||
beforeAll(() => {
|
||||
@ -335,7 +335,7 @@ function createDisplayOptions(extend: Partial<GetFieldDisplayValuesOptions> = {}
|
||||
overrides: [],
|
||||
defaults: {},
|
||||
},
|
||||
theme: getTestTheme(),
|
||||
theme: createTheme(),
|
||||
};
|
||||
|
||||
return merge<GetFieldDisplayValuesOptions, any>(options, extend);
|
||||
|
@ -15,7 +15,7 @@ import {
|
||||
TimeZone,
|
||||
} from '../types';
|
||||
import { DataFrameView } from '../dataframe/DataFrameView';
|
||||
import { GrafanaTheme } from '../types/theme';
|
||||
import { GrafanaThemeV2 } from '../themes';
|
||||
import { reduceField, ReducerID } from '../transformations/fieldReducer';
|
||||
import { ScopedVars } from '../types/ScopedVars';
|
||||
import { getTimeField } from '../dataframe/processDataFrame';
|
||||
@ -71,7 +71,7 @@ export interface GetFieldDisplayValuesOptions {
|
||||
fieldConfig: FieldConfigSource;
|
||||
replaceVariables: InterpolateFunction;
|
||||
sparkline?: boolean; // Calculate the sparkline
|
||||
theme: GrafanaTheme;
|
||||
theme: GrafanaThemeV2;
|
||||
timeZone?: TimeZone;
|
||||
}
|
||||
|
||||
|
@ -27,7 +27,7 @@ import { FieldConfigOptionsRegistry } from './FieldConfigOptionsRegistry';
|
||||
import { getFieldDisplayName } from './fieldState';
|
||||
import { ArrayVector } from '../vector';
|
||||
import { getDisplayProcessor } from './displayProcessor';
|
||||
import { getTestTheme } from '../utils/testdata/testTheme';
|
||||
import { createTheme } from '../themes';
|
||||
|
||||
const property1: any = {
|
||||
id: 'custom.property1', // Match field properties
|
||||
@ -179,7 +179,7 @@ describe('applyFieldOverrides', () => {
|
||||
overrides: [],
|
||||
},
|
||||
replaceVariables: (value: any) => value,
|
||||
theme: getTestTheme(),
|
||||
theme: createTheme(),
|
||||
fieldConfigRegistry: new FieldConfigOptionsRegistry(),
|
||||
});
|
||||
|
||||
@ -241,7 +241,7 @@ describe('applyFieldOverrides', () => {
|
||||
},
|
||||
fieldConfigRegistry: customFieldRegistry,
|
||||
replaceVariables: (v) => v,
|
||||
theme: getTestTheme(),
|
||||
theme: createTheme(),
|
||||
})[0];
|
||||
|
||||
const outField = processed.fields[0];
|
||||
@ -257,7 +257,7 @@ describe('applyFieldOverrides', () => {
|
||||
data: [f0], // the frame
|
||||
fieldConfig: src as FieldConfigSource, // defaults + overrides
|
||||
replaceVariables: (undefined as any) as InterpolateFunction,
|
||||
theme: getTestTheme(),
|
||||
theme: createTheme(),
|
||||
fieldConfigRegistry: customFieldRegistry,
|
||||
})[0];
|
||||
const valueColumn = data.fields[1];
|
||||
@ -284,7 +284,7 @@ describe('applyFieldOverrides', () => {
|
||||
data: [f0], // the frame
|
||||
fieldConfig: src as FieldConfigSource, // defaults + overrides
|
||||
replaceVariables: (undefined as any) as InterpolateFunction,
|
||||
theme: getTestTheme(),
|
||||
theme: createTheme(),
|
||||
})[0];
|
||||
const valueColumn = data.fields[1];
|
||||
const range = valueColumn.state!.range!;
|
||||
@ -306,7 +306,7 @@ describe('applyFieldOverrides', () => {
|
||||
replaceVariablesCalls.push(variables);
|
||||
return value;
|
||||
}) as InterpolateFunction,
|
||||
theme: getTestTheme(),
|
||||
theme: createTheme(),
|
||||
fieldConfigRegistry: customFieldRegistry,
|
||||
})[0];
|
||||
|
||||
@ -550,16 +550,7 @@ describe('getLinksSupplier', () => {
|
||||
});
|
||||
|
||||
const replaceSpy = jest.fn();
|
||||
const supplier = getLinksSupplier(
|
||||
f0,
|
||||
f0.fields[0],
|
||||
{},
|
||||
replaceSpy,
|
||||
// this is used only for internal links so isn't needed here
|
||||
{
|
||||
theme: getTestTheme(),
|
||||
}
|
||||
);
|
||||
const supplier = getLinksSupplier(f0, f0.fields[0], {}, replaceSpy);
|
||||
supplier({});
|
||||
|
||||
expect(replaceSpy).toBeCalledTimes(2);
|
||||
@ -594,6 +585,7 @@ describe('getLinksSupplier', () => {
|
||||
},
|
||||
],
|
||||
},
|
||||
display: (v) => ({ numeric: v, text: String(v) }),
|
||||
},
|
||||
],
|
||||
});
|
||||
@ -603,10 +595,11 @@ describe('getLinksSupplier', () => {
|
||||
f0.fields[0],
|
||||
{},
|
||||
// We do not need to interpolate anything for this test
|
||||
(value, vars, format) => value,
|
||||
{ theme: getTestTheme() }
|
||||
(value, vars, format) => value
|
||||
);
|
||||
|
||||
const links = supplier({ valueRowIndex: 0 });
|
||||
|
||||
expect(links.length).toBe(1);
|
||||
expect(links[0]).toEqual(
|
||||
expect.objectContaining({
|
||||
@ -786,23 +779,25 @@ describe('applyRawFieldOverrides', () => {
|
||||
fields: [numberAsEpoc, numberWithDecimals, numberAsBoolean, boolean, string, datetime],
|
||||
});
|
||||
|
||||
dataFrameA.fields[0].display = getDisplayProcessor({ field: dataFrameA.fields[0] });
|
||||
dataFrameA.fields[1].display = getDisplayProcessor({ field: dataFrameA.fields[1] });
|
||||
dataFrameA.fields[2].display = getDisplayProcessor({ field: dataFrameA.fields[2] });
|
||||
dataFrameA.fields[3].display = getDisplayProcessor({ field: dataFrameA.fields[3] });
|
||||
dataFrameA.fields[4].display = getDisplayProcessor({ field: dataFrameA.fields[4] });
|
||||
dataFrameA.fields[5].display = getDisplayProcessor({ field: dataFrameA.fields[5], timeZone: 'utc' });
|
||||
const theme = createTheme();
|
||||
|
||||
dataFrameA.fields[0].display = getDisplayProcessor({ field: dataFrameA.fields[0], theme });
|
||||
dataFrameA.fields[1].display = getDisplayProcessor({ field: dataFrameA.fields[1], theme });
|
||||
dataFrameA.fields[2].display = getDisplayProcessor({ field: dataFrameA.fields[2], theme });
|
||||
dataFrameA.fields[3].display = getDisplayProcessor({ field: dataFrameA.fields[3], theme });
|
||||
dataFrameA.fields[4].display = getDisplayProcessor({ field: dataFrameA.fields[4], theme });
|
||||
dataFrameA.fields[5].display = getDisplayProcessor({ field: dataFrameA.fields[5], theme, timeZone: 'utc' });
|
||||
|
||||
const dataFrameB: DataFrame = toDataFrame({
|
||||
fields: [numberAsEpoc, numberWithDecimals, numberAsBoolean, boolean, string, datetime],
|
||||
});
|
||||
|
||||
dataFrameB.fields[0].display = getDisplayProcessor({ field: dataFrameB.fields[0] });
|
||||
dataFrameB.fields[1].display = getDisplayProcessor({ field: dataFrameB.fields[1] });
|
||||
dataFrameB.fields[2].display = getDisplayProcessor({ field: dataFrameB.fields[2] });
|
||||
dataFrameB.fields[3].display = getDisplayProcessor({ field: dataFrameB.fields[3] });
|
||||
dataFrameB.fields[4].display = getDisplayProcessor({ field: dataFrameB.fields[4] });
|
||||
dataFrameB.fields[5].display = getDisplayProcessor({ field: dataFrameB.fields[5], timeZone: 'utc' });
|
||||
dataFrameB.fields[0].display = getDisplayProcessor({ field: dataFrameB.fields[0], theme });
|
||||
dataFrameB.fields[1].display = getDisplayProcessor({ field: dataFrameB.fields[1], theme });
|
||||
dataFrameB.fields[2].display = getDisplayProcessor({ field: dataFrameB.fields[2], theme });
|
||||
dataFrameB.fields[3].display = getDisplayProcessor({ field: dataFrameB.fields[3], theme });
|
||||
dataFrameB.fields[4].display = getDisplayProcessor({ field: dataFrameB.fields[4], theme });
|
||||
dataFrameB.fields[5].display = getDisplayProcessor({ field: dataFrameB.fields[5], theme, timeZone: 'utc' });
|
||||
|
||||
const data = [dataFrameA, dataFrameB];
|
||||
const rawData = applyRawFieldOverrides(data);
|
||||
|
@ -9,7 +9,6 @@ import {
|
||||
FieldConfigPropertyItem,
|
||||
FieldOverrideContext,
|
||||
FieldType,
|
||||
GrafanaTheme,
|
||||
InterpolateFunction,
|
||||
LinkModel,
|
||||
NumericRange,
|
||||
@ -206,10 +205,13 @@ export function applyFieldOverrides(options: ApplyFieldOverrideOptions): DataFra
|
||||
});
|
||||
|
||||
// Attach data links supplier
|
||||
newField.getLinks = getLinksSupplier(newFrame, newField, fieldScopedVars, context.replaceVariables, {
|
||||
theme: options.theme,
|
||||
timeZone: options.timeZone,
|
||||
});
|
||||
newField.getLinks = getLinksSupplier(
|
||||
newFrame,
|
||||
newField,
|
||||
fieldScopedVars,
|
||||
context.replaceVariables,
|
||||
options.timeZone
|
||||
);
|
||||
|
||||
return newField;
|
||||
});
|
||||
@ -324,10 +326,7 @@ export const getLinksSupplier = (
|
||||
field: Field,
|
||||
fieldScopedVars: ScopedVars,
|
||||
replaceVariables: InterpolateFunction,
|
||||
options: {
|
||||
theme: GrafanaTheme;
|
||||
timeZone?: TimeZone;
|
||||
}
|
||||
timeZone?: TimeZone
|
||||
) => (config: ValueLinkConfig): Array<LinkModel<Field>> => {
|
||||
if (!field.config.links || field.config.links.length === 0) {
|
||||
return [];
|
||||
@ -342,13 +341,19 @@ export const getLinksSupplier = (
|
||||
|
||||
// We are not displaying reduction result
|
||||
if (config.valueRowIndex !== undefined && !isNaN(config.valueRowIndex)) {
|
||||
const fieldsProxy = getFieldDisplayValuesProxy(frame, config.valueRowIndex, options);
|
||||
const fieldsProxy = getFieldDisplayValuesProxy({
|
||||
frame,
|
||||
rowIndex: config.valueRowIndex,
|
||||
timeZone: timeZone,
|
||||
});
|
||||
|
||||
valueVars = {
|
||||
raw: field.values.get(config.valueRowIndex),
|
||||
numeric: fieldsProxy[field.name].numeric,
|
||||
text: fieldsProxy[field.name].text,
|
||||
time: timeField ? timeField.values.get(config.valueRowIndex) : undefined,
|
||||
};
|
||||
|
||||
dataFrameVars = {
|
||||
__data: {
|
||||
value: {
|
||||
|
@ -1,8 +1,7 @@
|
||||
import { getFieldDisplayValuesProxy } from './getFieldDisplayValuesProxy';
|
||||
import { applyFieldOverrides } from './fieldOverrides';
|
||||
import { toDataFrame } from '../dataframe';
|
||||
import { GrafanaTheme } from '../types';
|
||||
import { getTestTheme } from '../utils/testdata/testTheme';
|
||||
import { createTheme } from '../themes';
|
||||
|
||||
describe('getFieldDisplayValuesProxy', () => {
|
||||
const data = applyFieldOverrides({
|
||||
@ -33,7 +32,7 @@ describe('getFieldDisplayValuesProxy', () => {
|
||||
},
|
||||
replaceVariables: (val: string) => val,
|
||||
timeZone: 'utc',
|
||||
theme: getTestTheme(),
|
||||
theme: createTheme(),
|
||||
})[0];
|
||||
|
||||
it('should define all display functions', () => {
|
||||
@ -45,9 +44,7 @@ describe('getFieldDisplayValuesProxy', () => {
|
||||
|
||||
it('should format the time values in UTC', () => {
|
||||
// Test Proxies in general
|
||||
const p = getFieldDisplayValuesProxy(data, 0, {
|
||||
theme: {} as GrafanaTheme,
|
||||
});
|
||||
const p = getFieldDisplayValuesProxy({ frame: data, rowIndex: 0 });
|
||||
const time = p.Time;
|
||||
expect(time.numeric).toEqual(1);
|
||||
expect(time.text).toEqual('1970-01-01 00:00:00');
|
||||
@ -58,9 +55,7 @@ describe('getFieldDisplayValuesProxy', () => {
|
||||
});
|
||||
|
||||
it('Lookup by name, index, or displayName', () => {
|
||||
const p = getFieldDisplayValuesProxy(data, 2, {
|
||||
theme: {} as GrafanaTheme,
|
||||
});
|
||||
const p = getFieldDisplayValuesProxy({ frame: data, rowIndex: 2 });
|
||||
expect(p.power.numeric).toEqual(300);
|
||||
expect(p['power'].numeric).toEqual(300);
|
||||
expect(p['POWAH!'].numeric).toEqual(300);
|
||||
@ -69,9 +64,7 @@ describe('getFieldDisplayValuesProxy', () => {
|
||||
});
|
||||
|
||||
it('should return undefined when missing', () => {
|
||||
const p = getFieldDisplayValuesProxy(data, 0, {
|
||||
theme: {} as GrafanaTheme,
|
||||
});
|
||||
const p = getFieldDisplayValuesProxy({ frame: data, rowIndex: 0 });
|
||||
expect(p.xyz).toBeUndefined();
|
||||
expect(p[100]).toBeUndefined();
|
||||
});
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { toNumber } from 'lodash';
|
||||
import { DataFrame, DisplayValue, GrafanaTheme, TimeZone } from '../types';
|
||||
import { getDisplayProcessor } from './displayProcessor';
|
||||
import { DataFrame, DisplayValue, TimeZone } from '../types';
|
||||
import { formattedValueToString } from '../valueFormats';
|
||||
|
||||
/**
|
||||
@ -10,30 +9,27 @@ import { formattedValueToString } from '../valueFormats';
|
||||
* @param options
|
||||
* @internal
|
||||
*/
|
||||
export function getFieldDisplayValuesProxy(
|
||||
frame: DataFrame,
|
||||
rowIndex: number,
|
||||
options: {
|
||||
theme: GrafanaTheme;
|
||||
timeZone?: TimeZone;
|
||||
}
|
||||
): Record<string, DisplayValue> {
|
||||
export function getFieldDisplayValuesProxy(options: {
|
||||
frame: DataFrame;
|
||||
rowIndex: number;
|
||||
timeZone?: TimeZone;
|
||||
}): Record<string, DisplayValue> {
|
||||
return new Proxy({} as Record<string, DisplayValue>, {
|
||||
get: (obj: any, key: string) => {
|
||||
// 1. Match the name
|
||||
let field = frame.fields.find((f) => key === f.name);
|
||||
let field = options.frame.fields.find((f) => key === f.name);
|
||||
if (!field) {
|
||||
// 2. Match the array index
|
||||
const k = toNumber(key);
|
||||
field = frame.fields[k];
|
||||
field = options.frame.fields[k];
|
||||
}
|
||||
if (!field) {
|
||||
// 3. Match the config displayName
|
||||
field = frame.fields.find((f) => key === f.config.displayName);
|
||||
field = options.frame.fields.find((f) => key === f.config.displayName);
|
||||
}
|
||||
if (!field) {
|
||||
// 4. Match the name label
|
||||
field = frame.fields.find((f) => {
|
||||
field = options.frame.fields.find((f) => {
|
||||
if (f.labels) {
|
||||
return key === f.labels.name;
|
||||
}
|
||||
@ -44,14 +40,9 @@ export function getFieldDisplayValuesProxy(
|
||||
return undefined;
|
||||
}
|
||||
if (!field.display) {
|
||||
// Lazy load the display processor
|
||||
field.display = getDisplayProcessor({
|
||||
field,
|
||||
theme: options.theme,
|
||||
timeZone: options.timeZone,
|
||||
});
|
||||
throw new Error('Field missing display processor ' + field.name);
|
||||
}
|
||||
const raw = field.values.get(rowIndex);
|
||||
const raw = field.values.get(options.rowIndex);
|
||||
const disp = field.display(raw);
|
||||
disp.toString = () => formattedValueToString(disp);
|
||||
return disp;
|
||||
|
@ -2,7 +2,7 @@ import { ThresholdsMode, Field, FieldType } from '../types';
|
||||
import { sortThresholds } from './thresholds';
|
||||
import { ArrayVector } from '../vector/ArrayVector';
|
||||
import { getScaleCalculator } from './scale';
|
||||
import { getTestTheme } from '../utils/testdata/testTheme';
|
||||
import { createTheme } from '../themes';
|
||||
|
||||
describe('getScaleCalculator', () => {
|
||||
it('should return percent, threshold and color', () => {
|
||||
@ -19,7 +19,7 @@ describe('getScaleCalculator', () => {
|
||||
values: new ArrayVector([0, 50, 100]),
|
||||
};
|
||||
|
||||
const calc = getScaleCalculator(field, getTestTheme());
|
||||
const calc = getScaleCalculator(field, createTheme());
|
||||
expect(calc(70)).toEqual({
|
||||
percent: 0.7,
|
||||
threshold: thresholds[1],
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { isNumber } from 'lodash';
|
||||
import { GrafanaThemeV2 } from '../themes/types';
|
||||
import { reduceField, ReducerID } from '../transformations/fieldReducer';
|
||||
import { Field, FieldConfig, FieldType, GrafanaTheme, NumericRange, Threshold } from '../types';
|
||||
import { Field, FieldConfig, FieldType, NumericRange, Threshold } from '../types';
|
||||
import { getFieldColorModeForField } from './fieldColor';
|
||||
import { getActiveThresholdForValue } from './thresholds';
|
||||
|
||||
@ -12,7 +13,7 @@ export interface ColorScaleValue {
|
||||
|
||||
export type ScaleCalculator = (value: number) => ColorScaleValue;
|
||||
|
||||
export function getScaleCalculator(field: Field, theme: GrafanaTheme): ScaleCalculator {
|
||||
export function getScaleCalculator(field: Field, theme: GrafanaThemeV2): ScaleCalculator {
|
||||
const mode = getFieldColorModeForField(field);
|
||||
const getColor = mode.getCalculator(field, theme);
|
||||
const info = field.state?.range ?? getMinMaxAndDelta(field);
|
||||
|
@ -2,6 +2,7 @@ import { DataSourceInstanceSettings } from './datasource';
|
||||
import { PanelPluginMeta } from './panel';
|
||||
import { GrafanaTheme } from './theme';
|
||||
import { SystemDateFormatSettings } from '../datetime';
|
||||
import { GrafanaThemeV2 } from '../themes';
|
||||
|
||||
/**
|
||||
* Describes the build information that will be available via the Grafana configuration.
|
||||
@ -123,6 +124,7 @@ export interface GrafanaConfig {
|
||||
editorsCanAdmin: boolean;
|
||||
disableSanitizeHtml: boolean;
|
||||
theme: GrafanaTheme;
|
||||
theme2: GrafanaThemeV2;
|
||||
pluginsToPreload: string[];
|
||||
featureToggles: FeatureToggles;
|
||||
licenseInfo: LicenseInfo;
|
||||
|
@ -1,9 +1,10 @@
|
||||
import { ComponentType } from 'react';
|
||||
import { MatcherConfig, FieldConfig, Field, DataFrame, GrafanaTheme, TimeZone } from '../types';
|
||||
import { MatcherConfig, FieldConfig, Field, DataFrame, TimeZone } from '../types';
|
||||
import { InterpolateFunction } from './panel';
|
||||
import { StandardEditorProps, FieldConfigOptionsRegistry, StandardEditorContext } from '../field';
|
||||
import { OptionsEditorItem } from './OptionsUIRegistryBuilder';
|
||||
import { OptionEditorConfig } from './options';
|
||||
import { GrafanaThemeV2 } from '../themes';
|
||||
|
||||
export interface DynamicConfigValue {
|
||||
id: string;
|
||||
@ -113,7 +114,7 @@ export interface ApplyFieldOverrideOptions {
|
||||
fieldConfig: FieldConfigSource;
|
||||
fieldConfigRegistry?: FieldConfigOptionsRegistry;
|
||||
replaceVariables: InterpolateFunction;
|
||||
theme: GrafanaTheme;
|
||||
theme: GrafanaThemeV2;
|
||||
timeZone?: TimeZone;
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,7 @@ import { getDataFrameRow, toDataFrameDTO } from '../dataframe/processDataFrame';
|
||||
import fs from 'fs';
|
||||
import { MutableDataFrame } from '../dataframe';
|
||||
import { getDisplayProcessor } from '../field';
|
||||
import { createTheme } from '../themes';
|
||||
|
||||
describe('read csv', () => {
|
||||
it('should get X and y', () => {
|
||||
@ -149,7 +150,11 @@ describe('DataFrame to CSV', () => {
|
||||
],
|
||||
});
|
||||
|
||||
dataFrame.fields[1].display = getDisplayProcessor({ field: dataFrame.fields[1], timeZone: 'utc' });
|
||||
dataFrame.fields[1].display = getDisplayProcessor({
|
||||
field: dataFrame.fields[1],
|
||||
timeZone: 'utc',
|
||||
theme: createTheme(),
|
||||
});
|
||||
|
||||
const csv = toCSV([dataFrame]);
|
||||
expect(csv).toMatchInlineSnapshot(`
|
||||
|
@ -1,11 +1,12 @@
|
||||
import { merge } from 'lodash';
|
||||
import { getTheme } from '@grafana/ui';
|
||||
import {
|
||||
BuildInfo,
|
||||
createTheme,
|
||||
DataSourceInstanceSettings,
|
||||
FeatureToggles,
|
||||
GrafanaConfig,
|
||||
GrafanaTheme,
|
||||
GrafanaThemeV2,
|
||||
LicenseInfo,
|
||||
PanelPluginMeta,
|
||||
systemDateFormats,
|
||||
@ -49,6 +50,7 @@ export class GrafanaBootConfig implements GrafanaConfig {
|
||||
editorsCanAdmin = false;
|
||||
disableSanitizeHtml = false;
|
||||
theme: GrafanaTheme;
|
||||
theme2: GrafanaThemeV2;
|
||||
pluginsToPreload: string[] = [];
|
||||
featureToggles: FeatureToggles = {
|
||||
live: false,
|
||||
@ -75,7 +77,9 @@ export class GrafanaBootConfig implements GrafanaConfig {
|
||||
awsAssumeRoleEnabled = false;
|
||||
|
||||
constructor(options: GrafanaBootConfig) {
|
||||
this.theme = getTheme(options.bootData.user.lightTheme ? 'light' : 'dark');
|
||||
const mode = options.bootData.user.lightTheme ? 'light' : 'dark';
|
||||
this.theme2 = createTheme({ colors: { mode } });
|
||||
this.theme = this.theme2.v1;
|
||||
|
||||
const defaults = {
|
||||
datasources: {},
|
||||
|
@ -4,7 +4,7 @@ import { withCenteredStory } from '../../utils/storybook/withCenteredStory';
|
||||
import { BarChart } from './BarChart';
|
||||
import { LegendDisplayMode } from '../VizLegend/models.gen';
|
||||
import { prepDataForStorybook } from '../../utils/storybook/data';
|
||||
import { useTheme } from '../../themes';
|
||||
import { useTheme2 } from '../../themes';
|
||||
import { select } from '@storybook/addon-knobs';
|
||||
import { BarChartOptions, BarValueVisibility } from './types';
|
||||
import { StackingMode } from '../uPlot/config';
|
||||
@ -42,7 +42,7 @@ const getKnobs = () => {
|
||||
export const Basic: React.FC = () => {
|
||||
const { legendPlacement, orientation } = getKnobs();
|
||||
|
||||
const theme = useTheme();
|
||||
const theme = useTheme2();
|
||||
const frame = toDataFrame({
|
||||
fields: [
|
||||
{ name: 'x', type: FieldType.string, values: ['group 1', 'group 2'] },
|
||||
|
@ -2,12 +2,12 @@ import React from 'react';
|
||||
import { AlignedData } from 'uplot';
|
||||
import { DataFrame, TimeRange } from '@grafana/data';
|
||||
import { VizLayout } from '../VizLayout/VizLayout';
|
||||
import { Themeable } from '../../types';
|
||||
import { Themeable2 } from '../../types';
|
||||
import { UPlotChart } from '../uPlot/Plot';
|
||||
import { UPlotConfigBuilder } from '../uPlot/config/UPlotConfigBuilder';
|
||||
import { GraphNGLegendEvent } from '../GraphNG/types';
|
||||
import { BarChartOptions } from './types';
|
||||
import { withTheme } from '../../themes';
|
||||
import { withTheme2 } from '../../themes/ThemeContext';
|
||||
import { preparePlotConfigBuilder, preparePlotFrame } from './utils';
|
||||
import { pluginLog, preparePlotData } from '../uPlot/utils';
|
||||
import { LegendDisplayMode } from '../VizLegend/models.gen';
|
||||
@ -16,7 +16,7 @@ import { PlotLegend } from '../uPlot/PlotLegend';
|
||||
/**
|
||||
* @alpha
|
||||
*/
|
||||
export interface BarChartProps extends Themeable, BarChartOptions {
|
||||
export interface BarChartProps extends Themeable2, BarChartOptions {
|
||||
height: number;
|
||||
width: number;
|
||||
data: DataFrame[];
|
||||
@ -130,5 +130,5 @@ class UnthemedBarChart extends React.Component<BarChartProps, BarChartState> {
|
||||
}
|
||||
}
|
||||
|
||||
export const BarChart = withTheme(UnthemedBarChart);
|
||||
export const BarChart = withTheme2(UnthemedBarChart);
|
||||
BarChart.displayName = 'GraphNG';
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
||||
import { preparePlotConfigBuilder, preparePlotFrame } from './utils';
|
||||
import { FieldConfig, FieldType, GrafanaTheme, MutableDataFrame, VizOrientation } from '@grafana/data';
|
||||
import { createTheme, FieldConfig, FieldType, MutableDataFrame, VizOrientation } from '@grafana/data';
|
||||
import { BarChartFieldConfig, BarChartOptions, BarValueVisibility } from './types';
|
||||
import { GraphGradientMode, StackingMode } from '../uPlot/config';
|
||||
import { LegendDisplayMode } from '../VizLegend/models.gen';
|
||||
@ -77,29 +77,28 @@ describe('GraphNG utils', () => {
|
||||
};
|
||||
|
||||
it.each([VizOrientation.Auto, VizOrientation.Horizontal, VizOrientation.Vertical])('orientation', (v) => {
|
||||
expect(
|
||||
preparePlotConfigBuilder(frame!, { colors: { panelBg: '#000000' } } as GrafanaTheme, {
|
||||
...config,
|
||||
orientation: v,
|
||||
})
|
||||
).toMatchSnapshot();
|
||||
const result = preparePlotConfigBuilder(frame!, createTheme(), {
|
||||
...config,
|
||||
orientation: v,
|
||||
}).getConfig();
|
||||
expect(result).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it.each([BarValueVisibility.Always, BarValueVisibility.Auto])('value visibility', (v) => {
|
||||
expect(
|
||||
preparePlotConfigBuilder(frame!, { colors: { panelBg: '#000000' } } as GrafanaTheme, {
|
||||
preparePlotConfigBuilder(frame!, createTheme(), {
|
||||
...config,
|
||||
showValue: v,
|
||||
})
|
||||
}).getConfig()
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it.each([StackingMode.None, StackingMode.Percent, StackingMode.Normal])('stacking', (v) => {
|
||||
expect(
|
||||
preparePlotConfigBuilder(frame!, { colors: { panelBg: '#000000' } } as GrafanaTheme, {
|
||||
preparePlotConfigBuilder(frame!, createTheme(), {
|
||||
...config,
|
||||
stacking: v,
|
||||
})
|
||||
}).getConfig()
|
||||
).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
@ -6,7 +6,7 @@ import {
|
||||
getFieldColorModeForField,
|
||||
getFieldDisplayName,
|
||||
getFieldSeriesColor,
|
||||
GrafanaTheme,
|
||||
GrafanaThemeV2,
|
||||
MutableDataFrame,
|
||||
VizOrientation,
|
||||
} from '@grafana/data';
|
||||
@ -18,7 +18,7 @@ import { FIXED_UNIT } from '../GraphNG/GraphNG';
|
||||
/** @alpha */
|
||||
export function preparePlotConfigBuilder(
|
||||
data: DataFrame,
|
||||
theme: GrafanaTheme,
|
||||
theme: GrafanaThemeV2,
|
||||
{ orientation, showValue, groupWidth, barWidth }: BarChartOptions
|
||||
) {
|
||||
const builder = new UPlotConfigBuilder();
|
||||
|
@ -5,7 +5,7 @@ import { VizOrientation, ThresholdsMode, Field, FieldType, getDisplayProcessor }
|
||||
import { Props } from './BarGauge';
|
||||
import { withCenteredStory } from '../../utils/storybook/withCenteredStory';
|
||||
import mdx from './BarGauge.mdx';
|
||||
import { useTheme } from '../../themes';
|
||||
import { useTheme2 } from '../../themes';
|
||||
|
||||
export default {
|
||||
title: 'Visualizations/BarGauge',
|
||||
@ -72,7 +72,7 @@ interface StoryProps extends Partial<Props> {
|
||||
}
|
||||
|
||||
const AddBarGaugeStory = (storyProps: StoryProps) => {
|
||||
const theme = useTheme();
|
||||
const theme = useTheme2();
|
||||
|
||||
const field: Partial<Field> = {
|
||||
type: FieldType.number,
|
||||
@ -89,7 +89,7 @@ const AddBarGaugeStory = (storyProps: StoryProps) => {
|
||||
},
|
||||
},
|
||||
};
|
||||
field.display = getDisplayProcessor({ field });
|
||||
field.display = getDisplayProcessor({ field, theme });
|
||||
|
||||
const props: Partial<Props> = {
|
||||
theme,
|
||||
|
@ -1,6 +1,14 @@
|
||||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
import { DisplayValue, VizOrientation, ThresholdsMode, Field, FieldType, getDisplayProcessor } from '@grafana/data';
|
||||
import {
|
||||
DisplayValue,
|
||||
VizOrientation,
|
||||
ThresholdsMode,
|
||||
Field,
|
||||
FieldType,
|
||||
getDisplayProcessor,
|
||||
createTheme,
|
||||
} from '@grafana/data';
|
||||
import {
|
||||
BarGauge,
|
||||
Props,
|
||||
@ -12,7 +20,6 @@ import {
|
||||
BarGaugeDisplayMode,
|
||||
calculateBarAndValueDimensions,
|
||||
} from './BarGauge';
|
||||
import { getTheme } from '../../themes';
|
||||
|
||||
const green = '#73BF69';
|
||||
const orange = '#FF9830';
|
||||
@ -33,7 +40,7 @@ function getProps(propOverrides?: Partial<Props>): Props {
|
||||
},
|
||||
},
|
||||
};
|
||||
const theme = getTheme();
|
||||
const theme = createTheme();
|
||||
field.display = getDisplayProcessor({ field, theme });
|
||||
|
||||
const props: Props = {
|
||||
|
@ -20,7 +20,7 @@ import {
|
||||
import { selectors } from '@grafana/e2e-selectors';
|
||||
import { FormattedValueDisplay } from '../FormattedValueDisplay/FormattedValueDisplay';
|
||||
import { measureText, calculateFontSize } from '../../utils/measureText';
|
||||
import { Themeable } from '../../types';
|
||||
import { Themeable2 } from '../../types';
|
||||
|
||||
const MIN_VALUE_HEIGHT = 18;
|
||||
const MAX_VALUE_HEIGHT = 50;
|
||||
@ -29,7 +29,7 @@ const TITLE_LINE_HEIGHT = 1.5;
|
||||
const VALUE_LINE_HEIGHT = 1;
|
||||
const VALUE_LEFT_PADDING = 10;
|
||||
|
||||
export interface Props extends Themeable {
|
||||
export interface Props extends Themeable2 {
|
||||
height: number;
|
||||
width: number;
|
||||
field: FieldConfig;
|
||||
@ -536,7 +536,7 @@ export function getBarGradient(props: Props, maxSize: number): string {
|
||||
|
||||
for (let i = 0; i < thresholds.steps.length; i++) {
|
||||
const threshold = thresholds.steps[i];
|
||||
const color = getColorForTheme(threshold.color, props.theme);
|
||||
const color = getColorForTheme(threshold.color, props.theme.v1);
|
||||
const valuePercent =
|
||||
thresholds.mode === ThresholdsMode.Percentage
|
||||
? threshold.value / 100
|
||||
@ -561,7 +561,7 @@ export function getBarGradient(props: Props, maxSize: number): string {
|
||||
}
|
||||
|
||||
if (mode.isContinuous && mode.colors) {
|
||||
const scheme = mode.colors.map((item) => getColorForTheme(item, theme));
|
||||
const scheme = mode.colors.map((item) => getColorForTheme(item, theme.v1));
|
||||
for (let i = 0; i < scheme.length; i++) {
|
||||
const color = scheme[i];
|
||||
|
||||
|
@ -10,7 +10,7 @@ import {
|
||||
} from './BigValue';
|
||||
import { withCenteredStory } from '../../utils/storybook/withCenteredStory';
|
||||
import mdx from './BigValue.mdx';
|
||||
import { useTheme } from '../../themes';
|
||||
import { useTheme2 } from '../../themes';
|
||||
import { ArrayVector, FieldSparkline, FieldType } from '@grafana/data';
|
||||
|
||||
export default {
|
||||
@ -68,7 +68,7 @@ export const Basic: Story<StoryProps> = ({
|
||||
textMode,
|
||||
justifyMode,
|
||||
}) => {
|
||||
const theme = useTheme();
|
||||
const theme = useTheme2();
|
||||
const sparkline: FieldSparkline = {
|
||||
y: {
|
||||
name: '',
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
import { BigValue, Props, BigValueColorMode, BigValueGraphMode } from './BigValue';
|
||||
import { getTheme } from '../../themes';
|
||||
import { createTheme } from '@grafana/data';
|
||||
|
||||
function getProps(propOverrides?: Partial<Props>): Props {
|
||||
const props: Props = {
|
||||
@ -13,7 +13,7 @@ function getProps(propOverrides?: Partial<Props>): Props {
|
||||
text: '25',
|
||||
numeric: 25,
|
||||
},
|
||||
theme: getTheme(),
|
||||
theme: createTheme(),
|
||||
};
|
||||
|
||||
Object.assign(props, propOverrides);
|
||||
|
@ -3,7 +3,7 @@ import React, { PureComponent } from 'react';
|
||||
import { DisplayValue, DisplayValueAlignmentFactors, FieldSparkline, TextDisplayOptions } from '@grafana/data';
|
||||
|
||||
// Types
|
||||
import { Themeable } from '../../types';
|
||||
import { Themeable2 } from '../../types';
|
||||
import { buildLayout } from './BigValueLayout';
|
||||
import { FormattedValueDisplay } from '../FormattedValueDisplay/FormattedValueDisplay';
|
||||
|
||||
@ -34,7 +34,7 @@ export enum BigValueTextMode {
|
||||
None = 'none',
|
||||
}
|
||||
|
||||
export interface Props extends Themeable {
|
||||
export interface Props extends Themeable2 {
|
||||
/** Height of the component */
|
||||
height: number;
|
||||
/** Width of the component */
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { Props, BigValueColorMode, BigValueGraphMode } from './BigValue';
|
||||
import { buildLayout, StackedWithChartLayout, WideWithChartLayout } from './BigValueLayout';
|
||||
import { getTheme } from '../../themes';
|
||||
import { ArrayVector, FieldType } from '@grafana/data';
|
||||
import { ArrayVector, createTheme, FieldType } from '@grafana/data';
|
||||
|
||||
function getProps(propOverrides?: Partial<Props>): Props {
|
||||
const props: Props = {
|
||||
@ -21,7 +20,7 @@ function getProps(propOverrides?: Partial<Props>): Props {
|
||||
config: {},
|
||||
},
|
||||
},
|
||||
theme: getTheme(),
|
||||
theme: createTheme(),
|
||||
};
|
||||
|
||||
Object.assign(props, propOverrides);
|
||||
|
@ -32,7 +32,7 @@ export abstract class BigValueLayout {
|
||||
constructor(private props: Props) {
|
||||
const { width, height, value, theme, text } = props;
|
||||
|
||||
this.valueColor = getColorForTheme(value.color || 'green', theme);
|
||||
this.valueColor = getColorForTheme(value.color || 'green', theme.v1);
|
||||
this.panelPadding = height > 100 ? 12 : 8;
|
||||
this.textValues = getTextValues(props);
|
||||
this.justifyCenter = shouldJustifyCenter(props.justifyMode, this.textValues.title);
|
||||
|
@ -2,7 +2,9 @@ import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import Graph from './Graph';
|
||||
import { VizTooltip, TooltipDisplayMode } from '../VizTooltip';
|
||||
import { GraphSeriesXY, FieldType, ArrayVector, dateTime, FieldColorModeId } from '@grafana/data';
|
||||
import { GraphSeriesXY, FieldType, ArrayVector, dateTime, FieldColorModeId, DisplayProcessor } from '@grafana/data';
|
||||
|
||||
const display: DisplayProcessor = (v) => ({ numeric: v, text: String(v), color: 'red' });
|
||||
|
||||
const series: GraphSeriesXY[] = [
|
||||
{
|
||||
@ -26,6 +28,7 @@ const series: GraphSeriesXY[] = [
|
||||
name: 'a-series',
|
||||
values: new ArrayVector([10, 20, 10]),
|
||||
config: { color: { mode: FieldColorModeId.Fixed, fixedColor: 'red' } },
|
||||
display,
|
||||
},
|
||||
timeStep: 3600000,
|
||||
yAxis: {
|
||||
@ -53,6 +56,7 @@ const series: GraphSeriesXY[] = [
|
||||
name: 'b-series',
|
||||
values: new ArrayVector([20, 30, 40]),
|
||||
config: { color: { mode: FieldColorModeId.Fixed, fixedColor: 'blue' } },
|
||||
display,
|
||||
},
|
||||
timeStep: 3600000,
|
||||
yAxis: {
|
||||
|
@ -4,7 +4,6 @@ import { GraphDimensions } from './GraphTooltip/types';
|
||||
import {
|
||||
FlotDataPoint,
|
||||
getValueFromDimension,
|
||||
getDisplayProcessor,
|
||||
Dimensions,
|
||||
dateTimeFormat,
|
||||
TimeZone,
|
||||
@ -60,12 +59,7 @@ export const GraphContextMenu: React.FC<GraphContextMenuProps> = ({
|
||||
contextDimensions.yAxis[0],
|
||||
contextDimensions.yAxis[1]
|
||||
);
|
||||
const display =
|
||||
source.series.valueField.display ??
|
||||
getDisplayProcessor({
|
||||
field: source.series.valueField,
|
||||
timeZone,
|
||||
});
|
||||
const display = source.series.valueField.display!;
|
||||
value = display(valueFromDimensions);
|
||||
}
|
||||
|
||||
|
@ -1,13 +1,15 @@
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
import { MultiModeGraphTooltip } from './MultiModeGraphTooltip';
|
||||
import { createDimension, ArrayVector, FieldType } from '@grafana/data';
|
||||
import { createDimension, ArrayVector, FieldType, DisplayProcessor } from '@grafana/data';
|
||||
import { GraphDimensions } from './types';
|
||||
import { ActiveDimensions } from '../../VizTooltip';
|
||||
|
||||
let dimensions: GraphDimensions;
|
||||
|
||||
describe('MultiModeGraphTooltip', () => {
|
||||
const display: DisplayProcessor = (v) => ({ numeric: v, text: String(v), color: 'red' });
|
||||
|
||||
describe('when shown when hovering over a datapoint', () => {
|
||||
beforeEach(() => {
|
||||
dimensions = {
|
||||
@ -17,12 +19,14 @@ describe('MultiModeGraphTooltip', () => {
|
||||
values: new ArrayVector([0, 100, 200]),
|
||||
name: 'A-series time',
|
||||
type: FieldType.time,
|
||||
display,
|
||||
},
|
||||
{
|
||||
config: {},
|
||||
values: new ArrayVector([0, 100, 200]),
|
||||
name: 'B-series time',
|
||||
type: FieldType.time,
|
||||
display,
|
||||
},
|
||||
]),
|
||||
yAxis: createDimension('yAxis', [
|
||||
@ -31,12 +35,14 @@ describe('MultiModeGraphTooltip', () => {
|
||||
values: new ArrayVector([10, 20, 10]),
|
||||
name: 'A-series values',
|
||||
type: FieldType.number,
|
||||
display,
|
||||
},
|
||||
{
|
||||
config: {},
|
||||
values: new ArrayVector([20, 30, 40]),
|
||||
name: 'B-series values',
|
||||
type: FieldType.number,
|
||||
display,
|
||||
},
|
||||
]),
|
||||
};
|
||||
|
@ -3,7 +3,6 @@ import {
|
||||
getValueFromDimension,
|
||||
getColumnFromDimension,
|
||||
formattedValueToString,
|
||||
getDisplayProcessor,
|
||||
getFieldDisplayName,
|
||||
} from '@grafana/data';
|
||||
import { SeriesTable } from '../../VizTooltip';
|
||||
@ -29,7 +28,7 @@ export const SingleModeGraphTooltip: React.FC<GraphTooltipContentProps> = ({
|
||||
|
||||
const valueField = getColumnFromDimension(dimensions.yAxis, activeDimensions.yAxis[0]);
|
||||
const value = getValueFromDimension(dimensions.yAxis, activeDimensions.yAxis[0], activeDimensions.yAxis[1]);
|
||||
const display = valueField.display ?? getDisplayProcessor({ field: valueField, timeZone });
|
||||
const display = valueField.display!;
|
||||
const disp = display(value);
|
||||
|
||||
return (
|
||||
|
@ -1,11 +1,13 @@
|
||||
import {
|
||||
GraphSeriesValue,
|
||||
toDataFrame,
|
||||
FieldType,
|
||||
FieldCache,
|
||||
FieldColorModeId,
|
||||
Field,
|
||||
getColorForTheme,
|
||||
applyFieldOverrides,
|
||||
createTheme,
|
||||
DataFrame,
|
||||
} from '@grafana/data';
|
||||
import { getTheme } from '../../themes';
|
||||
import { getMultiSeriesGraphHoverInfo, findHoverIndexFromData, graphTimeFormat } from './utils';
|
||||
@ -16,7 +18,7 @@ const mockResult = (
|
||||
seriesIndex: number,
|
||||
color?: string,
|
||||
label?: string,
|
||||
time?: GraphSeriesValue
|
||||
time?: string
|
||||
) => ({
|
||||
value,
|
||||
datapointIndex,
|
||||
@ -26,41 +28,62 @@ const mockResult = (
|
||||
time,
|
||||
});
|
||||
|
||||
function passThroughFieldOverrides(frame: DataFrame) {
|
||||
return applyFieldOverrides({
|
||||
data: [frame],
|
||||
fieldConfig: {
|
||||
defaults: {},
|
||||
overrides: [],
|
||||
},
|
||||
replaceVariables: (val: string) => val,
|
||||
timeZone: 'utc',
|
||||
theme: createTheme(),
|
||||
});
|
||||
}
|
||||
|
||||
// A and B series have the same x-axis range and the datapoints are x-axis aligned
|
||||
const aSeries = toDataFrame({
|
||||
fields: [
|
||||
{ name: 'time', type: FieldType.time, values: [100, 200, 300] },
|
||||
{
|
||||
name: 'value',
|
||||
type: FieldType.number,
|
||||
values: [10, 20, 10],
|
||||
config: { color: { mode: FieldColorModeId.Fixed, fixedColor: 'red' } },
|
||||
},
|
||||
],
|
||||
});
|
||||
const bSeries = toDataFrame({
|
||||
fields: [
|
||||
{ name: 'time', type: FieldType.time, values: [100, 200, 300] },
|
||||
{
|
||||
name: 'value',
|
||||
type: FieldType.number,
|
||||
values: [30, 60, 30],
|
||||
config: { color: { mode: FieldColorModeId.Fixed, fixedColor: 'blue' } },
|
||||
},
|
||||
],
|
||||
});
|
||||
const aSeries = passThroughFieldOverrides(
|
||||
toDataFrame({
|
||||
fields: [
|
||||
{ name: 'time', type: FieldType.time, values: [10000, 20000, 30000] },
|
||||
{
|
||||
name: 'value',
|
||||
type: FieldType.number,
|
||||
values: [10, 20, 10],
|
||||
config: { color: { mode: FieldColorModeId.Fixed, fixedColor: 'red' } },
|
||||
},
|
||||
],
|
||||
})
|
||||
)[0];
|
||||
|
||||
const bSeries = passThroughFieldOverrides(
|
||||
toDataFrame({
|
||||
fields: [
|
||||
{ name: 'time', type: FieldType.time, values: [10000, 20000, 30000] },
|
||||
{
|
||||
name: 'value',
|
||||
type: FieldType.number,
|
||||
values: [30, 60, 30],
|
||||
config: { color: { mode: FieldColorModeId.Fixed, fixedColor: 'blue' } },
|
||||
},
|
||||
],
|
||||
})
|
||||
)[0];
|
||||
|
||||
// C-series has the same x-axis range as A and B but is missing the middle point
|
||||
const cSeries = toDataFrame({
|
||||
fields: [
|
||||
{ name: 'time', type: FieldType.time, values: [100, 300] },
|
||||
{
|
||||
name: 'value',
|
||||
type: FieldType.number,
|
||||
values: [30, 30],
|
||||
config: { color: { mode: FieldColorModeId.Fixed, fixedColor: 'yellow' } },
|
||||
},
|
||||
],
|
||||
});
|
||||
const cSeries = passThroughFieldOverrides(
|
||||
toDataFrame({
|
||||
fields: [
|
||||
{ name: 'time', type: FieldType.time, values: [10000, 30000] },
|
||||
{
|
||||
name: 'value',
|
||||
type: FieldType.number,
|
||||
values: [30, 30],
|
||||
config: { color: { mode: FieldColorModeId.Fixed, fixedColor: 'yellow' } },
|
||||
},
|
||||
],
|
||||
})
|
||||
)[0];
|
||||
|
||||
function getFixedThemedColor(field: Field): string {
|
||||
return getColorForTheme(field.config.color!.fixedColor!, getTheme());
|
||||
@ -78,12 +101,12 @@ describe('Graph utils', () => {
|
||||
const bTimeField = bCache.getFieldByName('time');
|
||||
|
||||
const result = getMultiSeriesGraphHoverInfo([aValueField!, bValueField!], [aTimeField!, bTimeField!], 0);
|
||||
expect(result.time).toBe(100);
|
||||
expect(result.time).toBe('1970-01-01 00:00:10');
|
||||
expect(result.results[0]).toEqual(
|
||||
mockResult('10', 0, 0, getFixedThemedColor(aValueField!), aValueField!.name, 100)
|
||||
mockResult('10', 0, 0, getFixedThemedColor(aValueField!), aValueField!.name, '1970-01-01 00:00:10')
|
||||
);
|
||||
expect(result.results[1]).toEqual(
|
||||
mockResult('30', 0, 1, getFixedThemedColor(bValueField!), bValueField!.name, 100)
|
||||
mockResult('30', 0, 1, getFixedThemedColor(bValueField!), bValueField!.name, '1970-01-01 00:00:10')
|
||||
);
|
||||
});
|
||||
|
||||
@ -97,13 +120,13 @@ describe('Graph utils', () => {
|
||||
const bTimeField = bCache.getFieldByName('time');
|
||||
|
||||
// hovering right before middle point
|
||||
const result = getMultiSeriesGraphHoverInfo([aValueField!, bValueField!], [aTimeField!, bTimeField!], 199);
|
||||
expect(result.time).toBe(100);
|
||||
const result = getMultiSeriesGraphHoverInfo([aValueField!, bValueField!], [aTimeField!, bTimeField!], 19900);
|
||||
expect(result.time).toBe('1970-01-01 00:00:10');
|
||||
expect(result.results[0]).toEqual(
|
||||
mockResult('10', 0, 0, getFixedThemedColor(aValueField!), aValueField!.name, 100)
|
||||
mockResult('10', 0, 0, getFixedThemedColor(aValueField!), aValueField!.name, '1970-01-01 00:00:10')
|
||||
);
|
||||
expect(result.results[1]).toEqual(
|
||||
mockResult('30', 0, 1, getFixedThemedColor(bValueField!), bValueField!.name, 100)
|
||||
mockResult('30', 0, 1, getFixedThemedColor(bValueField!), bValueField!.name, '1970-01-01 00:00:10')
|
||||
);
|
||||
});
|
||||
|
||||
@ -116,13 +139,13 @@ describe('Graph utils', () => {
|
||||
const bTimeField = bCache.getFieldByName('time');
|
||||
|
||||
// hovering right after middle point
|
||||
const result = getMultiSeriesGraphHoverInfo([aValueField!, bValueField!], [aTimeField!, bTimeField!], 201);
|
||||
expect(result.time).toBe(200);
|
||||
const result = getMultiSeriesGraphHoverInfo([aValueField!, bValueField!], [aTimeField!, bTimeField!], 20100);
|
||||
expect(result.time).toBe('1970-01-01 00:00:20');
|
||||
expect(result.results[0]).toEqual(
|
||||
mockResult('20', 1, 0, getFixedThemedColor(aValueField!), aValueField!.name, 200)
|
||||
mockResult('20', 1, 0, getFixedThemedColor(aValueField!), aValueField!.name, '1970-01-01 00:00:20')
|
||||
);
|
||||
expect(result.results[1]).toEqual(
|
||||
mockResult('60', 1, 1, getFixedThemedColor(bValueField!), bValueField!.name, 200)
|
||||
mockResult('60', 1, 1, getFixedThemedColor(bValueField!), bValueField!.name, '1970-01-01 00:00:20')
|
||||
);
|
||||
});
|
||||
});
|
||||
@ -141,17 +164,17 @@ describe('Graph utils', () => {
|
||||
|
||||
// hovering on a middle point
|
||||
// aSeries has point at that time, cSeries doesn't
|
||||
const result = getMultiSeriesGraphHoverInfo([aValueField!, cValueField!], [aTimeField!, cTimeField!], 200);
|
||||
const result = getMultiSeriesGraphHoverInfo([aValueField!, cValueField!], [aTimeField!, cTimeField!], 20000);
|
||||
|
||||
// we expect a time of the hovered point
|
||||
expect(result.time).toBe(200);
|
||||
expect(result.time).toBe('1970-01-01 00:00:20');
|
||||
// we expect middle point from aSeries (the one we are hovering over)
|
||||
expect(result.results[0]).toEqual(
|
||||
mockResult('20', 1, 0, getFixedThemedColor(aValueField!), aValueField!.name, 200)
|
||||
mockResult('20', 1, 0, getFixedThemedColor(aValueField!), aValueField!.name, '1970-01-01 00:00:20')
|
||||
);
|
||||
// we expect closest point before hovered point from cSeries (1st point)
|
||||
expect(result.results[1]).toEqual(
|
||||
mockResult('30', 0, 1, getFixedThemedColor(cValueField!), cValueField!.name, 100)
|
||||
mockResult('30', 0, 1, getFixedThemedColor(cValueField!), cValueField!.name, '1970-01-01 00:00:10')
|
||||
);
|
||||
});
|
||||
|
||||
@ -164,17 +187,17 @@ describe('Graph utils', () => {
|
||||
const cTimeField = cCache.getFieldByName('time');
|
||||
|
||||
// aSeries has point at that time, cSeries doesn't
|
||||
const result = getMultiSeriesGraphHoverInfo([aValueField!, cValueField!], [aTimeField!, cTimeField!], 201);
|
||||
const result = getMultiSeriesGraphHoverInfo([aValueField!, cValueField!], [aTimeField!, cTimeField!], 20100);
|
||||
|
||||
// we expect the time of the closest point before hover
|
||||
expect(result.time).toBe(200);
|
||||
expect(result.time).toBe('1970-01-01 00:00:20');
|
||||
// we expect the closest datapoint before hover from aSeries
|
||||
expect(result.results[0]).toEqual(
|
||||
mockResult('20', 1, 0, getFixedThemedColor(aValueField!), aValueField!.name, 200)
|
||||
mockResult('20', 1, 0, getFixedThemedColor(aValueField!), aValueField!.name, '1970-01-01 00:00:20')
|
||||
);
|
||||
// we expect the closest datapoint before hover from cSeries (1st point)
|
||||
expect(result.results[1]).toEqual(
|
||||
mockResult('30', 0, 1, getFixedThemedColor(cValueField!), cValueField!.name, 100)
|
||||
mockResult('30', 0, 1, getFixedThemedColor(cValueField!), cValueField!.name, '1970-01-01 00:00:10')
|
||||
);
|
||||
});
|
||||
});
|
||||
@ -187,13 +210,13 @@ describe('Graph utils', () => {
|
||||
// hovering over 1st datapoint
|
||||
expect(findHoverIndexFromData(timeField!, 0)).toBe(0);
|
||||
// hovering over right before 2nd datapoint
|
||||
expect(findHoverIndexFromData(timeField!, 199)).toBe(0);
|
||||
expect(findHoverIndexFromData(timeField!, 19900)).toBe(0);
|
||||
// hovering over 2nd datapoint
|
||||
expect(findHoverIndexFromData(timeField!, 200)).toBe(1);
|
||||
expect(findHoverIndexFromData(timeField!, 20000)).toBe(1);
|
||||
// hovering over right before 3rd datapoint
|
||||
expect(findHoverIndexFromData(timeField!, 299)).toBe(1);
|
||||
expect(findHoverIndexFromData(timeField!, 29900)).toBe(1);
|
||||
// hovering over 3rd datapoint
|
||||
expect(findHoverIndexFromData(timeField!, 300)).toBe(2);
|
||||
expect(findHoverIndexFromData(timeField!, 30000)).toBe(2);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -2,7 +2,6 @@ import {
|
||||
GraphSeriesValue,
|
||||
Field,
|
||||
formattedValueToString,
|
||||
getDisplayProcessor,
|
||||
getFieldDisplayName,
|
||||
TimeZone,
|
||||
dateTimeFormat,
|
||||
@ -85,8 +84,7 @@ export const getMultiSeriesGraphHoverInfo = (
|
||||
minTime = time.display ? formattedValueToString(time.display(pointTime)) : pointTime;
|
||||
}
|
||||
|
||||
const display = field.display ?? getDisplayProcessor({ field, timeZone });
|
||||
const disp = display(field.values.get(hoverIndex));
|
||||
const disp = field.display!(field.values.get(hoverIndex));
|
||||
|
||||
results.push({
|
||||
value: formattedValueToString(disp),
|
||||
|
@ -4,7 +4,7 @@ import { withCenteredStory } from '../../utils/storybook/withCenteredStory';
|
||||
import { GraphNG, GraphNGProps } from './GraphNG';
|
||||
import { LegendDisplayMode, LegendPlacement } from '../VizLegend/models.gen';
|
||||
import { prepDataForStorybook } from '../../utils/storybook/data';
|
||||
import { useTheme } from '../../themes';
|
||||
import { useTheme2 } from '../../themes';
|
||||
import { Story } from '@storybook/react';
|
||||
|
||||
export default {
|
||||
@ -34,7 +34,7 @@ interface StoryProps extends GraphNGProps {
|
||||
unit: string;
|
||||
}
|
||||
export const Lines: Story<StoryProps> = ({ placement, unit, legendDisplayMode, ...args }) => {
|
||||
const theme = useTheme();
|
||||
const theme = useTheme2();
|
||||
const seriesA = toDataFrame({
|
||||
target: 'SeriesA',
|
||||
datapoints: [
|
||||
|
@ -1,8 +1,7 @@
|
||||
import React from 'react';
|
||||
import { AlignedData } from 'uplot';
|
||||
import { DataFrame, FieldMatcherID, fieldMatchers, TimeRange, TimeZone } from '@grafana/data';
|
||||
import { withTheme } from '../../themes';
|
||||
import { Themeable } from '../../types';
|
||||
import { Themeable2 } from '../../types';
|
||||
import { UPlotConfigBuilder } from '../uPlot/config/UPlotConfigBuilder';
|
||||
import { GraphNGLegendEvent, XYFieldMatchers } from './types';
|
||||
import { preparePlotConfigBuilder, preparePlotFrame } from './utils';
|
||||
@ -11,13 +10,14 @@ import { PlotLegend } from '../uPlot/PlotLegend';
|
||||
import { UPlotChart } from '../uPlot/Plot';
|
||||
import { LegendDisplayMode, VizLegendOptions } from '../VizLegend/models.gen';
|
||||
import { VizLayout } from '../VizLayout/VizLayout';
|
||||
import { withTheme2 } from '../../themes/ThemeContext';
|
||||
|
||||
/**
|
||||
* @internal -- not a public API
|
||||
*/
|
||||
export const FIXED_UNIT = '__fixed';
|
||||
|
||||
export interface GraphNGProps extends Themeable {
|
||||
export interface GraphNGProps extends Themeable2 {
|
||||
width: number;
|
||||
height: number;
|
||||
data: DataFrame[];
|
||||
@ -158,5 +158,5 @@ class UnthemedGraphNG extends React.Component<GraphNGProps, GraphNGState> {
|
||||
}
|
||||
}
|
||||
|
||||
export const GraphNG = withTheme(UnthemedGraphNG);
|
||||
export const GraphNG = withTheme2(UnthemedGraphNG);
|
||||
GraphNG.displayName = 'GraphNG';
|
||||
|
@ -1,36 +1,57 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`GraphNG utils preparePlotConfigBuilder 1`] = `
|
||||
UPlotConfigBuilder {
|
||||
"axes": Object {
|
||||
"__fixed": UPlotAxisBuilder {
|
||||
"props": Object {
|
||||
"formatValue": [Function],
|
||||
"label": undefined,
|
||||
"placement": "left",
|
||||
"scaleKey": "__fixed",
|
||||
"size": undefined,
|
||||
"theme": Object {
|
||||
"colors": Object {
|
||||
"panelBg": "#000000",
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"axes": Array [
|
||||
Object {
|
||||
"font": "12px \\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif",
|
||||
"gap": 5,
|
||||
"grid": Object {
|
||||
"show": true,
|
||||
"stroke": "rgba(240, 250, 255, 0.09)",
|
||||
"width": 1,
|
||||
},
|
||||
},
|
||||
"x": UPlotAxisBuilder {
|
||||
"props": Object {
|
||||
"isTime": true,
|
||||
"placement": "bottom",
|
||||
"scaleKey": "x",
|
||||
"theme": Object {
|
||||
"colors": Object {
|
||||
"panelBg": "#000000",
|
||||
},
|
||||
},
|
||||
"timeZone": "utc",
|
||||
"labelFont": "12px \\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif",
|
||||
"scale": "x",
|
||||
"show": true,
|
||||
"side": 2,
|
||||
"size": [Function],
|
||||
"space": [Function],
|
||||
"splits": undefined,
|
||||
"stroke": "rgb(201, 209, 217)",
|
||||
"ticks": Object {
|
||||
"show": true,
|
||||
"stroke": "rgba(240, 250, 255, 0.09)",
|
||||
"width": 1,
|
||||
},
|
||||
"timeZone": "utc",
|
||||
"values": [Function],
|
||||
},
|
||||
},
|
||||
Object {
|
||||
"font": "12px \\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif",
|
||||
"gap": 5,
|
||||
"grid": Object {
|
||||
"show": true,
|
||||
"stroke": "rgba(240, 250, 255, 0.09)",
|
||||
"width": 1,
|
||||
},
|
||||
"labelFont": "12px \\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif",
|
||||
"scale": "__fixed",
|
||||
"show": true,
|
||||
"side": 3,
|
||||
"size": [Function],
|
||||
"space": [Function],
|
||||
"splits": undefined,
|
||||
"stroke": "rgb(201, 209, 217)",
|
||||
"ticks": Object {
|
||||
"show": true,
|
||||
"stroke": "rgba(240, 250, 255, 0.09)",
|
||||
"width": 1,
|
||||
},
|
||||
"timeZone": undefined,
|
||||
"values": [Function],
|
||||
},
|
||||
],
|
||||
"bands": Array [
|
||||
Object {
|
||||
"series": Array [
|
||||
@ -45,252 +66,143 @@ UPlotConfigBuilder {
|
||||
],
|
||||
},
|
||||
],
|
||||
"hasBottomAxis": true,
|
||||
"hasLeftAxis": true,
|
||||
"cursor": Object {
|
||||
"drag": Object {
|
||||
"setScale": false,
|
||||
},
|
||||
"focus": Object {
|
||||
"prox": 30,
|
||||
},
|
||||
"points": Object {
|
||||
"fill": [Function],
|
||||
"size": [Function],
|
||||
"stroke": [Function],
|
||||
"width": [Function],
|
||||
},
|
||||
},
|
||||
"hooks": Object {},
|
||||
"isStacking": true,
|
||||
"scales": Array [
|
||||
UPlotScaleBuilder {
|
||||
"props": Object {
|
||||
"direction": 1,
|
||||
"isTime": true,
|
||||
"orientation": 0,
|
||||
"range": [Function],
|
||||
"scaleKey": "x",
|
||||
},
|
||||
"scales": Object {
|
||||
"__fixed": Object {
|
||||
"auto": true,
|
||||
"dir": 1,
|
||||
"distr": 1,
|
||||
"log": undefined,
|
||||
"ori": 1,
|
||||
"range": [Function],
|
||||
"time": undefined,
|
||||
},
|
||||
UPlotScaleBuilder {
|
||||
"props": Object {
|
||||
"direction": 1,
|
||||
"distribution": undefined,
|
||||
"log": undefined,
|
||||
"max": undefined,
|
||||
"min": undefined,
|
||||
"orientation": 1,
|
||||
"scaleKey": "__fixed",
|
||||
"softMax": undefined,
|
||||
"softMin": undefined,
|
||||
},
|
||||
"x": Object {
|
||||
"auto": false,
|
||||
"dir": 1,
|
||||
"ori": 0,
|
||||
"range": [Function],
|
||||
"time": true,
|
||||
},
|
||||
],
|
||||
},
|
||||
"select": undefined,
|
||||
"series": Array [
|
||||
UPlotSeriesBuilder {
|
||||
"props": Object {
|
||||
"barAlignment": undefined,
|
||||
"colorMode": Object {
|
||||
"description": "Derive colors from thresholds",
|
||||
"getCalculator": [Function],
|
||||
"id": "thresholds",
|
||||
"isByValue": true,
|
||||
"name": "From thresholds",
|
||||
},
|
||||
"dataFrameFieldIndex": Object {
|
||||
"fieldIndex": 1,
|
||||
"frameIndex": 0,
|
||||
},
|
||||
"drawStyle": "line",
|
||||
"fieldName": "Metric 1",
|
||||
"fillOpacity": 0.1,
|
||||
"gradientMode": "opacity",
|
||||
"hideInLegend": undefined,
|
||||
"lineColor": "#ff0000",
|
||||
"lineInterpolation": "linear",
|
||||
"lineStyle": Object {
|
||||
"dash": Array [
|
||||
1,
|
||||
2,
|
||||
],
|
||||
"fill": "dash",
|
||||
},
|
||||
"lineWidth": 2,
|
||||
"pointColor": "#808080",
|
||||
"pointSize": undefined,
|
||||
"scaleKey": "__fixed",
|
||||
Object {},
|
||||
Object {
|
||||
"dash": Array [
|
||||
1,
|
||||
2,
|
||||
],
|
||||
"fill": [Function],
|
||||
"paths": [Function],
|
||||
"points": Object {
|
||||
"fill": "#808080",
|
||||
"show": true,
|
||||
"showPoints": "always",
|
||||
"spanNulls": false,
|
||||
"theme": Object {
|
||||
"colors": Object {
|
||||
"panelBg": "#000000",
|
||||
},
|
||||
},
|
||||
"thresholds": undefined,
|
||||
"size": undefined,
|
||||
"stroke": "#808080",
|
||||
},
|
||||
"pxAlign": undefined,
|
||||
"scale": "__fixed",
|
||||
"show": true,
|
||||
"spanGaps": false,
|
||||
"stroke": "#ff0000",
|
||||
"width": 2,
|
||||
},
|
||||
UPlotSeriesBuilder {
|
||||
"props": Object {
|
||||
"barAlignment": -1,
|
||||
"colorMode": Object {
|
||||
"description": "Derive colors from thresholds",
|
||||
"getCalculator": [Function],
|
||||
"id": "thresholds",
|
||||
"isByValue": true,
|
||||
"name": "From thresholds",
|
||||
},
|
||||
"dataFrameFieldIndex": Object {
|
||||
"fieldIndex": 1,
|
||||
"frameIndex": 1,
|
||||
},
|
||||
"drawStyle": "bars",
|
||||
"fieldName": "Metric 2",
|
||||
"fillOpacity": 0.1,
|
||||
"gradientMode": "hue",
|
||||
"hideInLegend": undefined,
|
||||
"lineColor": "#ff0000",
|
||||
"lineInterpolation": "linear",
|
||||
"lineStyle": Object {
|
||||
"dash": Array [
|
||||
1,
|
||||
2,
|
||||
],
|
||||
"fill": "dash",
|
||||
},
|
||||
"lineWidth": 2,
|
||||
"pointColor": "#808080",
|
||||
"pointSize": undefined,
|
||||
"scaleKey": "__fixed",
|
||||
Object {
|
||||
"dash": Array [
|
||||
1,
|
||||
2,
|
||||
],
|
||||
"fill": [Function],
|
||||
"paths": [Function],
|
||||
"points": Object {
|
||||
"fill": "#808080",
|
||||
"show": true,
|
||||
"showPoints": "always",
|
||||
"spanNulls": false,
|
||||
"theme": Object {
|
||||
"colors": Object {
|
||||
"panelBg": "#000000",
|
||||
},
|
||||
},
|
||||
"thresholds": undefined,
|
||||
"size": undefined,
|
||||
"stroke": "#808080",
|
||||
},
|
||||
"pxAlign": undefined,
|
||||
"scale": "__fixed",
|
||||
"show": true,
|
||||
"spanGaps": false,
|
||||
"stroke": "#ff0000",
|
||||
"width": 2,
|
||||
},
|
||||
UPlotSeriesBuilder {
|
||||
"props": Object {
|
||||
"barAlignment": undefined,
|
||||
"colorMode": Object {
|
||||
"description": "Derive colors from thresholds",
|
||||
"getCalculator": [Function],
|
||||
"id": "thresholds",
|
||||
"isByValue": true,
|
||||
"name": "From thresholds",
|
||||
},
|
||||
"dataFrameFieldIndex": Object {
|
||||
"fieldIndex": 2,
|
||||
"frameIndex": 1,
|
||||
},
|
||||
"drawStyle": "line",
|
||||
"fieldName": "Metric 3",
|
||||
"fillOpacity": 0.1,
|
||||
"gradientMode": "opacity",
|
||||
"hideInLegend": undefined,
|
||||
"lineColor": "#ff0000",
|
||||
"lineInterpolation": "linear",
|
||||
"lineStyle": Object {
|
||||
"dash": Array [
|
||||
1,
|
||||
2,
|
||||
],
|
||||
"fill": "dash",
|
||||
},
|
||||
"lineWidth": 2,
|
||||
"pointColor": "#808080",
|
||||
"pointSize": undefined,
|
||||
"scaleKey": "__fixed",
|
||||
Object {
|
||||
"dash": Array [
|
||||
1,
|
||||
2,
|
||||
],
|
||||
"fill": [Function],
|
||||
"paths": [Function],
|
||||
"points": Object {
|
||||
"fill": "#808080",
|
||||
"show": true,
|
||||
"showPoints": "always",
|
||||
"spanNulls": false,
|
||||
"theme": Object {
|
||||
"colors": Object {
|
||||
"panelBg": "#000000",
|
||||
},
|
||||
},
|
||||
"thresholds": undefined,
|
||||
"size": undefined,
|
||||
"stroke": "#808080",
|
||||
},
|
||||
"pxAlign": undefined,
|
||||
"scale": "__fixed",
|
||||
"show": true,
|
||||
"spanGaps": false,
|
||||
"stroke": "#ff0000",
|
||||
"width": 2,
|
||||
},
|
||||
UPlotSeriesBuilder {
|
||||
"props": Object {
|
||||
"barAlignment": -1,
|
||||
"colorMode": Object {
|
||||
"description": "Derive colors from thresholds",
|
||||
"getCalculator": [Function],
|
||||
"id": "thresholds",
|
||||
"isByValue": true,
|
||||
"name": "From thresholds",
|
||||
},
|
||||
"dataFrameFieldIndex": Object {
|
||||
"fieldIndex": 3,
|
||||
"frameIndex": 1,
|
||||
},
|
||||
"drawStyle": "bars",
|
||||
"fieldName": "Metric 4",
|
||||
"fillOpacity": 0.1,
|
||||
"gradientMode": "hue",
|
||||
"hideInLegend": undefined,
|
||||
"lineColor": "#ff0000",
|
||||
"lineInterpolation": "linear",
|
||||
"lineStyle": Object {
|
||||
"dash": Array [
|
||||
1,
|
||||
2,
|
||||
],
|
||||
"fill": "dash",
|
||||
},
|
||||
"lineWidth": 2,
|
||||
"pointColor": "#808080",
|
||||
"pointSize": undefined,
|
||||
"scaleKey": "__fixed",
|
||||
Object {
|
||||
"dash": Array [
|
||||
1,
|
||||
2,
|
||||
],
|
||||
"fill": [Function],
|
||||
"paths": [Function],
|
||||
"points": Object {
|
||||
"fill": "#808080",
|
||||
"show": true,
|
||||
"showPoints": "always",
|
||||
"spanNulls": false,
|
||||
"theme": Object {
|
||||
"colors": Object {
|
||||
"panelBg": "#000000",
|
||||
},
|
||||
},
|
||||
"thresholds": undefined,
|
||||
"size": undefined,
|
||||
"stroke": "#808080",
|
||||
},
|
||||
"pxAlign": undefined,
|
||||
"scale": "__fixed",
|
||||
"show": true,
|
||||
"spanGaps": false,
|
||||
"stroke": "#ff0000",
|
||||
"width": 2,
|
||||
},
|
||||
UPlotSeriesBuilder {
|
||||
"props": Object {
|
||||
"barAlignment": -1,
|
||||
"colorMode": Object {
|
||||
"description": "Derive colors from thresholds",
|
||||
"getCalculator": [Function],
|
||||
"id": "thresholds",
|
||||
"isByValue": true,
|
||||
"name": "From thresholds",
|
||||
},
|
||||
"dataFrameFieldIndex": Object {
|
||||
"fieldIndex": 4,
|
||||
"frameIndex": 1,
|
||||
},
|
||||
"drawStyle": "bars",
|
||||
"fieldName": "Metric 4",
|
||||
"fillOpacity": 0.1,
|
||||
"gradientMode": "hue",
|
||||
"hideInLegend": undefined,
|
||||
"lineColor": "#ff0000",
|
||||
"lineInterpolation": "linear",
|
||||
"lineStyle": Object {
|
||||
"dash": Array [
|
||||
1,
|
||||
2,
|
||||
],
|
||||
"fill": "dash",
|
||||
},
|
||||
"lineWidth": 2,
|
||||
"pointColor": "#808080",
|
||||
"pointSize": undefined,
|
||||
"scaleKey": "__fixed",
|
||||
Object {
|
||||
"dash": Array [
|
||||
1,
|
||||
2,
|
||||
],
|
||||
"fill": [Function],
|
||||
"paths": [Function],
|
||||
"points": Object {
|
||||
"fill": "#808080",
|
||||
"show": true,
|
||||
"showPoints": "always",
|
||||
"spanNulls": false,
|
||||
"theme": Object {
|
||||
"colors": Object {
|
||||
"panelBg": "#000000",
|
||||
},
|
||||
},
|
||||
"thresholds": undefined,
|
||||
"size": undefined,
|
||||
"stroke": "#808080",
|
||||
},
|
||||
"pxAlign": undefined,
|
||||
"scale": "__fixed",
|
||||
"show": true,
|
||||
"spanGaps": false,
|
||||
"stroke": "#ff0000",
|
||||
"width": 2,
|
||||
},
|
||||
],
|
||||
"tz": "UTC",
|
||||
"tzDate": [Function],
|
||||
}
|
||||
`;
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { preparePlotConfigBuilder, preparePlotFrame } from './utils';
|
||||
import {
|
||||
createTheme,
|
||||
DefaultTimeZone,
|
||||
FieldConfig,
|
||||
FieldMatcherID,
|
||||
fieldMatchers,
|
||||
FieldType,
|
||||
getDefaultTimeRange,
|
||||
GrafanaTheme,
|
||||
MutableDataFrame,
|
||||
} from '@grafana/data';
|
||||
import {
|
||||
@ -188,13 +188,12 @@ jest.mock('@grafana/data', () => ({
|
||||
describe('GraphNG utils', () => {
|
||||
test('preparePlotConfigBuilder', () => {
|
||||
const frame = mockDataFrame();
|
||||
expect(
|
||||
preparePlotConfigBuilder(
|
||||
frame!,
|
||||
{ colors: { panelBg: '#000000' } } as GrafanaTheme,
|
||||
getDefaultTimeRange,
|
||||
() => DefaultTimeZone
|
||||
)
|
||||
).toMatchSnapshot();
|
||||
const result = preparePlotConfigBuilder(
|
||||
frame!,
|
||||
createTheme(),
|
||||
getDefaultTimeRange,
|
||||
() => DefaultTimeZone
|
||||
).getConfig();
|
||||
expect(result).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
@ -10,7 +10,7 @@ import {
|
||||
getFieldColorModeForField,
|
||||
getFieldDisplayName,
|
||||
getFieldSeriesColor,
|
||||
GrafanaTheme,
|
||||
GrafanaThemeV2,
|
||||
outerJoinDataFrames,
|
||||
TimeRange,
|
||||
TimeZone,
|
||||
@ -83,7 +83,7 @@ export function preparePlotFrame(frames: DataFrame[], dimFields: XYFieldMatchers
|
||||
|
||||
export function preparePlotConfigBuilder(
|
||||
frame: DataFrame,
|
||||
theme: GrafanaTheme,
|
||||
theme: GrafanaThemeV2,
|
||||
getTimeRange: () => TimeRange,
|
||||
getTimeZone: () => TimeZone
|
||||
): UPlotConfigBuilder {
|
||||
|
@ -6,11 +6,11 @@ import { EdgeDatum, NodeDatum } from './types';
|
||||
import { Node } from './Node';
|
||||
import { Edge } from './Edge';
|
||||
import { ViewControls } from './ViewControls';
|
||||
import { DataFrame, GrafanaTheme, LinkModel } from '@grafana/data';
|
||||
import { DataFrame, GrafanaThemeV2, LinkModel } from '@grafana/data';
|
||||
import { useZoom } from './useZoom';
|
||||
import { Bounds, Config, defaultConfig, useLayout } from './layout';
|
||||
import { EdgeArrowMarker } from './EdgeArrowMarker';
|
||||
import { stylesFactory, useTheme } from '../../themes';
|
||||
import { stylesFactory, useTheme2 } from '../../themes';
|
||||
import { css } from '@emotion/css';
|
||||
import { useCategorizeFrames } from './useCategorizeFrames';
|
||||
import { EdgeLabel } from './EdgeLabel';
|
||||
@ -19,7 +19,7 @@ import { processNodes } from './utils';
|
||||
import { Icon } from '..';
|
||||
import { useNodeLimit } from './useNodeLimit';
|
||||
|
||||
const getStyles = stylesFactory((theme: GrafanaTheme) => ({
|
||||
const getStyles = stylesFactory((theme: GrafanaThemeV2) => ({
|
||||
wrapper: css`
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
@ -52,13 +52,13 @@ const getStyles = stylesFactory((theme: GrafanaTheme) => ({
|
||||
padding: 5px 8px;
|
||||
font-size: 10px;
|
||||
text-shadow: 0 1px 0 rgba(0, 0, 0, 0.2);
|
||||
border-radius: ${theme.border.radius.md};
|
||||
border-radius: ${theme.shape.borderRadius()};
|
||||
align-items: center;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
background: ${theme.palette.warn};
|
||||
color: ${theme.palette.white};
|
||||
background: ${theme.colors.warning.main};
|
||||
color: ${theme.colors.warning.contrastText};
|
||||
`,
|
||||
}));
|
||||
|
||||
@ -87,7 +87,7 @@ export function NodeGraph({ getLinks, dataFrames, nodeLimit }: Props) {
|
||||
const firstNodesDataFrame = nodesDataFrames[0];
|
||||
const firstEdgesDataFrame = edgesDataFrames[0];
|
||||
|
||||
const theme = useTheme();
|
||||
const theme = useTheme2();
|
||||
|
||||
// TODO we should be able to allow multiple dataframes for both edges and nodes, could be issue with node ids which in
|
||||
// that case should be unique or figure a way to link edges and nodes dataframes together.
|
||||
|
@ -5,7 +5,7 @@ describe('processNodes', () => {
|
||||
const theme = createTheme();
|
||||
|
||||
it('handles empty args', async () => {
|
||||
expect(processNodes(undefined, undefined, theme.v1)).toEqual({ nodes: [], edges: [] });
|
||||
expect(processNodes(undefined, undefined, theme)).toEqual({ nodes: [], edges: [] });
|
||||
});
|
||||
|
||||
it('returns proper nodes and edges', async () => {
|
||||
@ -17,7 +17,7 @@ describe('processNodes', () => {
|
||||
[0, 2],
|
||||
[1, 2],
|
||||
]),
|
||||
theme.v1
|
||||
theme
|
||||
)
|
||||
).toEqual({
|
||||
nodes: [
|
||||
|
@ -5,7 +5,7 @@ import {
|
||||
FieldCache,
|
||||
FieldType,
|
||||
getFieldColorModeForField,
|
||||
GrafanaTheme,
|
||||
GrafanaThemeV2,
|
||||
MutableDataFrame,
|
||||
} from '@grafana/data';
|
||||
import { EdgeDatum, NodeDatum } from './types';
|
||||
@ -84,7 +84,7 @@ export enum DataFrameFieldNames {
|
||||
export function processNodes(
|
||||
nodes: DataFrame | undefined,
|
||||
edges: DataFrame | undefined,
|
||||
theme: GrafanaTheme
|
||||
theme: GrafanaThemeV2
|
||||
): { nodes: NodeDatum[]; edges: EdgeDatum[] } {
|
||||
if (!nodes) {
|
||||
return { nodes: [], edges: [] };
|
||||
@ -276,7 +276,7 @@ function edgesFrame() {
|
||||
});
|
||||
}
|
||||
|
||||
function getColor(field: Field, index: number, theme: GrafanaTheme): string {
|
||||
function getColor(field: Field, index: number, theme: GrafanaThemeV2): string {
|
||||
if (!field.config.color) {
|
||||
return field.values.get(index);
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ export function PieChart(props: PieChartProps) {
|
||||
fieldConfig,
|
||||
reduceOptions,
|
||||
data,
|
||||
theme: theme.v1,
|
||||
theme: theme,
|
||||
replaceVariables,
|
||||
timeZone,
|
||||
});
|
||||
|
@ -19,11 +19,11 @@ import {
|
||||
} from '../uPlot/config';
|
||||
import { UPlotConfigBuilder } from '../uPlot/config/UPlotConfigBuilder';
|
||||
import { UPlotChart } from '../uPlot/Plot';
|
||||
import { Themeable } from '../../types';
|
||||
import { Themeable2 } from '../../types';
|
||||
import { preparePlotData } from '../uPlot/utils';
|
||||
import { preparePlotFrame } from './utils';
|
||||
|
||||
export interface SparklineProps extends Themeable {
|
||||
export interface SparklineProps extends Themeable2 {
|
||||
width: number;
|
||||
height: number;
|
||||
config?: FieldConfig<GraphFieldConfig>;
|
||||
@ -144,6 +144,7 @@ export class Sparkline extends PureComponent<SparklineProps, State> {
|
||||
min: field.config.min,
|
||||
max: field.config.max,
|
||||
});
|
||||
|
||||
builder.addAxis({
|
||||
scaleKey,
|
||||
theme,
|
||||
|
@ -3,12 +3,12 @@ import { merge } from 'lodash';
|
||||
import { Table } from '@grafana/ui';
|
||||
import { withCenteredStory } from '../../utils/storybook/withCenteredStory';
|
||||
import { number } from '@storybook/addon-knobs';
|
||||
import { useTheme } from '../../themes';
|
||||
import { useTheme2 } from '../../themes';
|
||||
import mdx from './Table.mdx';
|
||||
import {
|
||||
DataFrame,
|
||||
FieldType,
|
||||
GrafanaTheme,
|
||||
GrafanaThemeV2,
|
||||
MutableDataFrame,
|
||||
ThresholdsConfig,
|
||||
ThresholdsMode,
|
||||
@ -27,7 +27,7 @@ export default {
|
||||
},
|
||||
};
|
||||
|
||||
function buildData(theme: GrafanaTheme, config: Record<string, FieldConfig>): DataFrame {
|
||||
function buildData(theme: GrafanaThemeV2, config: Record<string, FieldConfig>): DataFrame {
|
||||
const data = new MutableDataFrame({
|
||||
fields: [
|
||||
{ name: 'Time', type: FieldType.time, values: [] }, // The time field
|
||||
@ -100,7 +100,7 @@ const defaultThresholds: ThresholdsConfig = {
|
||||
};
|
||||
|
||||
export const Simple = () => {
|
||||
const theme = useTheme();
|
||||
const theme = useTheme2();
|
||||
const width = number('width', 700, {}, 'Props');
|
||||
const data = buildData(theme, {});
|
||||
|
||||
@ -112,7 +112,7 @@ export const Simple = () => {
|
||||
};
|
||||
|
||||
export const BarGaugeCell = () => {
|
||||
const theme = useTheme();
|
||||
const theme = useTheme2();
|
||||
const width = number('width', 700, {}, 'Props');
|
||||
const data = buildData(theme, {
|
||||
Progress: {
|
||||
@ -132,7 +132,7 @@ export const BarGaugeCell = () => {
|
||||
};
|
||||
|
||||
export const ColoredCells = () => {
|
||||
const theme = useTheme();
|
||||
const theme = useTheme2();
|
||||
const width = number('width', 750, {}, 'Props');
|
||||
const data = buildData(theme, {
|
||||
Progress: {
|
||||
|
@ -1,10 +1,8 @@
|
||||
import React from 'react';
|
||||
import { render, screen, within } from '@testing-library/react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import { applyFieldOverrides, DataFrame, FieldType, toDataFrame } from '@grafana/data';
|
||||
|
||||
import { applyFieldOverrides, createTheme, DataFrame, FieldType, toDataFrame } from '@grafana/data';
|
||||
import { Props, Table } from './Table';
|
||||
import { getTheme } from '../../themes';
|
||||
|
||||
function getDefaultDataFrame(): DataFrame {
|
||||
const dataFrame = toDataFrame({
|
||||
@ -67,7 +65,7 @@ function getDefaultDataFrame(): DataFrame {
|
||||
return vars && value === '${__value.text}' ? vars['__value'].value.text : value;
|
||||
},
|
||||
timeZone: 'utc',
|
||||
theme: getTheme(),
|
||||
theme: createTheme(),
|
||||
});
|
||||
return dataFrames[0];
|
||||
}
|
||||
|
@ -15,7 +15,6 @@ import {
|
||||
} from 'react-table';
|
||||
import { FixedSizeList } from 'react-window';
|
||||
import { getColumns, sortCaseInsensitive } from './utils';
|
||||
import { useTheme } from '../../themes';
|
||||
import {
|
||||
TableColumnResizeActionCallback,
|
||||
TableFilterActionCallback,
|
||||
@ -27,6 +26,7 @@ import { Icon } from '../Icon/Icon';
|
||||
import { CustomScrollbar } from '../CustomScrollbar/CustomScrollbar';
|
||||
import { Filter } from './Filter';
|
||||
import { TableCell } from './TableCell';
|
||||
import { useStyles2 } from '../../themes';
|
||||
|
||||
const COLUMN_MIN_WIDTH = 150;
|
||||
|
||||
@ -123,8 +123,7 @@ export const Table: FC<Props> = memo((props: Props) => {
|
||||
resizable = true,
|
||||
initialSortBy,
|
||||
} = props;
|
||||
const theme = useTheme();
|
||||
const tableStyles = getTableStyles(theme);
|
||||
const tableStyles = useStyles2(getTableStyles);
|
||||
|
||||
// React table data array. This data acts just like a dummy array to let react-table know how many rows exist
|
||||
// The cells use the field to look up values
|
||||
|
@ -1,18 +1,17 @@
|
||||
import { css, cx } from '@emotion/css';
|
||||
import { GrafanaTheme } from '@grafana/data';
|
||||
import { styleMixins, stylesFactory } from '../../themes';
|
||||
import { GrafanaThemeV2 } from '@grafana/data';
|
||||
import { getScrollbarWidth } from '../../utils';
|
||||
|
||||
export const getTableStyles = stylesFactory((theme: GrafanaTheme) => {
|
||||
const { palette, colors } = theme;
|
||||
const headerBg = theme.colors.bg2;
|
||||
const borderColor = theme.colors.border1;
|
||||
const resizerColor = theme.isLight ? palette.blue95 : palette.blue77;
|
||||
export const getTableStyles = (theme: GrafanaThemeV2) => {
|
||||
const { colors } = theme;
|
||||
const headerBg = theme.colors.background.secondary;
|
||||
const borderColor = theme.colors.border.weak;
|
||||
const resizerColor = theme.colors.primary.border;
|
||||
const cellPadding = 6;
|
||||
const lineHeight = theme.typography.lineHeight.md;
|
||||
const lineHeight = theme.typography.body.lineHeight;
|
||||
const bodyFontSize = 14;
|
||||
const cellHeight = cellPadding * 2 + bodyFontSize * lineHeight;
|
||||
const rowHoverBg = styleMixins.hoverColor(theme.colors.bg1, theme);
|
||||
const rowHoverBg = theme.colors.emphasize(theme.colors.background.primary, 0.03);
|
||||
const lastChildExtraPadding = Math.max(getScrollbarWidth(), cellPadding);
|
||||
|
||||
const buildCellContainerStyle = (color?: string, background?: string) => {
|
||||
@ -35,7 +34,7 @@ export const getTableStyles = stylesFactory((theme: GrafanaTheme) => {
|
||||
&:hover {
|
||||
overflow: visible;
|
||||
width: auto !important;
|
||||
box-shadow: 0 0 2px ${theme.colors.formFocusOutline};
|
||||
box-shadow: 0 0 2px ${theme.colors.primary.main};
|
||||
background: ${background ?? rowHoverBg};
|
||||
z-index: 1;
|
||||
|
||||
@ -72,8 +71,8 @@ export const getTableStyles = stylesFactory((theme: GrafanaTheme) => {
|
||||
padding: ${cellPadding}px;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
color: ${colors.textBlue};
|
||||
border-right: 1px solid ${theme.colors.panelBg};
|
||||
color: ${colors.primary.text};
|
||||
border-right: 1px solid ${theme.colors.border.weak};
|
||||
display: flex;
|
||||
|
||||
&:last-child {
|
||||
@ -86,7 +85,7 @@ export const getTableStyles = stylesFactory((theme: GrafanaTheme) => {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: flex;
|
||||
margin-right: ${theme.spacing.xs};
|
||||
margin-right: ${theme.spacing(0.5)};
|
||||
`,
|
||||
cellContainer: buildCellContainerStyle(),
|
||||
cellText: css`
|
||||
@ -145,14 +144,14 @@ export const getTableStyles = stylesFactory((theme: GrafanaTheme) => {
|
||||
justify-content: flex-end;
|
||||
flex-grow: 1;
|
||||
opacity: 0.6;
|
||||
padding-left: ${theme.spacing.xxs};
|
||||
padding-left: ${theme.spacing(0.25)};
|
||||
`,
|
||||
'cell-filter-actions'
|
||||
),
|
||||
filterItem: css`
|
||||
label: filterItem;
|
||||
cursor: pointer;
|
||||
padding: 0 ${theme.spacing.xxs};
|
||||
padding: 0 ${theme.spacing(0.025)};
|
||||
`,
|
||||
noData: css`
|
||||
align-items: center;
|
||||
@ -162,6 +161,6 @@ export const getTableStyles = stylesFactory((theme: GrafanaTheme) => {
|
||||
width: 100%;
|
||||
`,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
export type TableStyles = ReturnType<typeof getTableStyles>;
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import { FieldMatcherID, fieldMatchers } from '@grafana/data';
|
||||
import { withTheme } from '../../themes';
|
||||
import { withTheme2 } from '../../themes/ThemeContext';
|
||||
import { GraphNGState } from '../GraphNG/GraphNG';
|
||||
import { preparePlotConfigBuilder, preparePlotFrame } from './utils'; // << preparePlotConfigBuilder is really the only change vs GraphNG
|
||||
import { pluginLog, preparePlotData } from '../uPlot/utils';
|
||||
@ -146,5 +146,5 @@ class UnthemedTimelineChart extends React.Component<TimelineProps, GraphNGState>
|
||||
}
|
||||
}
|
||||
|
||||
export const TimelineChart = withTheme(UnthemedTimelineChart);
|
||||
export const TimelineChart = withTheme2(UnthemedTimelineChart);
|
||||
TimelineChart.displayName = 'TimelineChart';
|
||||
|
@ -6,12 +6,12 @@ import {
|
||||
FieldConfig,
|
||||
formattedValueToString,
|
||||
getFieldDisplayName,
|
||||
GrafanaTheme,
|
||||
outerJoinDataFrames,
|
||||
TimeRange,
|
||||
TimeZone,
|
||||
classicColors,
|
||||
Field,
|
||||
GrafanaThemeV2,
|
||||
} from '@grafana/data';
|
||||
import { UPlotConfigBuilder } from '../uPlot/config/UPlotConfigBuilder';
|
||||
import { TimelineCoreOptions, getConfig } from './timeline';
|
||||
@ -45,14 +45,14 @@ export function preparePlotFrame(data: DataFrame[], dimFields: XYFieldMatchers)
|
||||
|
||||
export type uPlotConfigBuilderSupplier = (
|
||||
frame: DataFrame,
|
||||
theme: GrafanaTheme,
|
||||
theme: GrafanaThemeV2,
|
||||
getTimeRange: () => TimeRange,
|
||||
getTimeZone: () => TimeZone
|
||||
) => UPlotConfigBuilder;
|
||||
|
||||
export function preparePlotConfigBuilder(
|
||||
frame: DataFrame,
|
||||
theme: GrafanaTheme,
|
||||
theme: GrafanaThemeV2,
|
||||
getTimeRange: () => TimeRange,
|
||||
getTimeZone: () => TimeZone,
|
||||
coreOptions: Partial<TimelineCoreOptions>
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { dateTimeFormat, GrafanaTheme, systemDateFormats, TimeZone } from '@grafana/data';
|
||||
import { dateTimeFormat, GrafanaThemeV2, systemDateFormats, TimeZone } from '@grafana/data';
|
||||
import uPlot, { Axis } from 'uplot';
|
||||
import { PlotConfigBuilder } from '../types';
|
||||
import { measureText } from '../../../utils/measureText';
|
||||
@ -7,7 +7,7 @@ import { optMinMax } from './UPlotScaleBuilder';
|
||||
|
||||
export interface AxisProps {
|
||||
scaleKey: string;
|
||||
theme: GrafanaTheme;
|
||||
theme: GrafanaThemeV2;
|
||||
label?: string;
|
||||
show?: boolean;
|
||||
size?: number | null;
|
||||
@ -50,14 +50,14 @@ export class UPlotAxisBuilder extends PlotConfigBuilder<AxisProps, Axis> {
|
||||
theme,
|
||||
} = this.props;
|
||||
|
||||
const font = `12px ${theme.typography.fontFamily.sansSerif}`;
|
||||
const font = `12px ${theme.typography.fontFamily}`;
|
||||
|
||||
const gridColor = theme.isDark ? 'rgba(240, 250, 255, 0.09)' : 'rgba(0, 10, 23, 0.09)';
|
||||
|
||||
let config: Axis = {
|
||||
scale: scaleKey,
|
||||
show,
|
||||
stroke: theme.colors.text,
|
||||
stroke: theme.colors.text.primary,
|
||||
side: getUPlotSideFromAxis(placement),
|
||||
font,
|
||||
labelFont: font,
|
||||
|
@ -13,7 +13,7 @@ import {
|
||||
import { createTheme } from '@grafana/data';
|
||||
|
||||
describe('UPlotConfigBuilder', () => {
|
||||
const darkTheme = createTheme().v1;
|
||||
const darkTheme = createTheme();
|
||||
|
||||
describe('default config', () => {
|
||||
it('builds default config', () => {
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { DataFrameFieldIndex, FALLBACK_COLOR, FieldColorMode, GrafanaTheme, ThresholdsConfig } from '@grafana/data';
|
||||
import { DataFrameFieldIndex, FALLBACK_COLOR, FieldColorMode, GrafanaThemeV2, ThresholdsConfig } from '@grafana/data';
|
||||
import tinycolor from 'tinycolor2';
|
||||
import uPlot, { Series } from 'uplot';
|
||||
import {
|
||||
@ -30,7 +30,7 @@ export interface SeriesProps extends LineConfig, BarConfig, FillConfig, PointsCo
|
||||
show?: boolean;
|
||||
dataFrameFieldIndex?: DataFrameFieldIndex;
|
||||
hideInLegend?: boolean;
|
||||
theme: GrafanaTheme;
|
||||
theme: GrafanaThemeV2;
|
||||
}
|
||||
|
||||
export class UPlotSeriesBuilder extends PlotConfigBuilder<SeriesProps, Series> {
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { FieldColorMode, GrafanaTheme, ThresholdsConfig } from '@grafana/data';
|
||||
import { FieldColorMode, GrafanaThemeV2, ThresholdsConfig } from '@grafana/data';
|
||||
import tinycolor from 'tinycolor2';
|
||||
import uPlot from 'uplot';
|
||||
import { getCanvasContext } from '../../../utils/measureText';
|
||||
@ -20,7 +20,7 @@ export function getOpacityGradientFn(
|
||||
export function getHueGradientFn(
|
||||
color: string,
|
||||
opacity: number,
|
||||
theme: GrafanaTheme
|
||||
theme: GrafanaThemeV2
|
||||
): (self: uPlot, seriesIdx: number) => CanvasGradient {
|
||||
return (plot: uPlot, seriesIdx: number) => {
|
||||
const ctx = getCanvasContext();
|
||||
|
@ -13,6 +13,7 @@ import {
|
||||
import { SeriesTable, SeriesTableRowProps, TooltipDisplayMode, VizTooltipContainer } from '../../VizTooltip';
|
||||
import { UPlotConfigBuilder } from '../config/UPlotConfigBuilder';
|
||||
import { pluginLog } from '../utils';
|
||||
import { useTheme2 } from '../../../themes/ThemeContext';
|
||||
|
||||
interface TooltipPluginProps {
|
||||
mode?: TooltipDisplayMode;
|
||||
@ -30,6 +31,7 @@ export const TooltipPlugin: React.FC<TooltipPluginProps> = ({
|
||||
config,
|
||||
...otherProps
|
||||
}) => {
|
||||
const theme = useTheme2();
|
||||
const plotCtx = usePlotContext();
|
||||
const plotCanvas = useRef<HTMLDivElement>();
|
||||
const plotCanvasBBox = useRef<any>({ left: 0, top: 0, right: 0, bottom: 0, width: 0, height: 0 });
|
||||
@ -81,7 +83,7 @@ export const TooltipPlugin: React.FC<TooltipPluginProps> = ({
|
||||
if (!xField) {
|
||||
return null;
|
||||
}
|
||||
const xFieldFmt = xField.display || getDisplayProcessor({ field: xField, timeZone });
|
||||
const xFieldFmt = xField.display || getDisplayProcessor({ field: xField, timeZone, theme });
|
||||
let tooltip = null;
|
||||
|
||||
const xVal = xFieldFmt(xField!.values.get(focusedPointIdx)).text;
|
||||
@ -91,7 +93,7 @@ export const TooltipPlugin: React.FC<TooltipPluginProps> = ({
|
||||
const field = otherProps.data.fields[focusedSeriesIdx];
|
||||
const plotSeries = plotCtx.plot.series;
|
||||
|
||||
const fieldFmt = field.display || getDisplayProcessor({ field, timeZone });
|
||||
const fieldFmt = field.display || getDisplayProcessor({ field, timeZone, theme });
|
||||
const value = fieldFmt(plotCtx.plot.data[focusedSeriesIdx!][focusedPointIdx]);
|
||||
|
||||
tooltip = (
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { applyFieldOverrides, DataFrame, GrafanaTheme } from '@grafana/data';
|
||||
import { applyFieldOverrides, DataFrame, GrafanaThemeV2 } from '@grafana/data';
|
||||
|
||||
export function prepDataForStorybook(data: DataFrame[], theme: GrafanaTheme) {
|
||||
export function prepDataForStorybook(data: DataFrame[], theme: GrafanaThemeV2) {
|
||||
return applyFieldOverrides({
|
||||
data: data,
|
||||
fieldConfig: {
|
||||
|
@ -32,6 +32,7 @@ import {
|
||||
rangeUtil,
|
||||
} from '@grafana/data';
|
||||
import { getThemeColor } from 'app/core/utils/colors';
|
||||
import { config } from '@grafana/runtime';
|
||||
|
||||
export const LIMIT_LABEL = 'Line limit';
|
||||
|
||||
@ -146,6 +147,7 @@ export function makeSeriesForLogs(sortedRows: LogRowModel[], bucketSize: number,
|
||||
timeField.display = getDisplayProcessor({
|
||||
field: timeField,
|
||||
timeZone,
|
||||
theme: config.theme2,
|
||||
});
|
||||
|
||||
const valueField = fieldCache.getFirstFieldOfType(FieldType.number)!;
|
||||
@ -155,7 +157,7 @@ export function makeSeriesForLogs(sortedRows: LogRowModel[], bucketSize: number,
|
||||
};
|
||||
|
||||
valueField.name = series.alias;
|
||||
const fieldDisplayProcessor = getDisplayProcessor({ field: valueField, timeZone });
|
||||
const fieldDisplayProcessor = getDisplayProcessor({ field: valueField, timeZone, theme: config.theme2 });
|
||||
valueField.display = (value: any) => ({ ...fieldDisplayProcessor(value), color: series.color });
|
||||
|
||||
const points = getFlotPairs({
|
||||
|
@ -218,7 +218,7 @@ function handleJSONResponse(frames: DataFrameJSON[]) {
|
||||
overrides: [],
|
||||
},
|
||||
replaceVariables: (value: any) => value,
|
||||
theme: config.theme,
|
||||
theme: config.theme2,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -476,7 +476,7 @@ export class PanelModel implements DataConfigSource {
|
||||
fieldConfig: this.fieldConfig,
|
||||
replaceVariables: this.replaceVariables,
|
||||
fieldConfigRegistry: this.plugin.fieldConfigRegistry,
|
||||
theme: config.theme,
|
||||
theme: config.theme2,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,7 @@ export function loadSnapshotData(panel: PanelModel, dashboard: DashboardModel):
|
||||
},
|
||||
replaceVariables: panel.replaceVariables,
|
||||
fieldConfigRegistry: panel.plugin!.fieldConfigRegistry,
|
||||
theme: config.theme,
|
||||
theme: config.theme2,
|
||||
timeZone: dashboard.getTimezone(),
|
||||
}),
|
||||
annotations,
|
||||
|
@ -19,7 +19,7 @@ import {
|
||||
LegendDisplayMode,
|
||||
TooltipPlugin,
|
||||
useStyles,
|
||||
useTheme,
|
||||
useTheme2,
|
||||
ZoomPlugin,
|
||||
TooltipDisplayMode,
|
||||
} from '@grafana/ui';
|
||||
@ -55,7 +55,7 @@ export function ExploreGraphNGPanel({
|
||||
annotations,
|
||||
splitOpenFn,
|
||||
}: Props) {
|
||||
const theme = useTheme();
|
||||
const theme = useTheme2();
|
||||
const [showAllTimeSeries, setShowAllTimeSeries] = useState(false);
|
||||
const [structureRev, setStructureRev] = useState(1);
|
||||
const [fieldConfig, setFieldConfig] = useState<FieldConfigSource>({
|
||||
|
@ -39,7 +39,7 @@ export const getGraphSeriesModel = (
|
||||
decimals: legendOptions.decimals,
|
||||
},
|
||||
},
|
||||
theme: config.theme,
|
||||
theme: config.theme2,
|
||||
timeZone,
|
||||
});
|
||||
|
||||
@ -106,7 +106,7 @@ export const getGraphSeriesModel = (
|
||||
}
|
||||
: { ...field.config, color };
|
||||
|
||||
field.display = getDisplayProcessor({ field, timeZone, theme: config.theme });
|
||||
field.display = getDisplayProcessor({ field, timeZone, theme: config.theme2 });
|
||||
|
||||
// Time step is used to determine bars width when graph is rendered as bar chart
|
||||
const timeStep = getSeriesTimeStep(timeField);
|
||||
@ -121,7 +121,7 @@ export const getGraphSeriesModel = (
|
||||
unit: systemDateFormats.getTimeFieldUnit(useMsDateFormat),
|
||||
},
|
||||
},
|
||||
theme: config.theme,
|
||||
theme: config.theme2,
|
||||
});
|
||||
|
||||
graphs.push({
|
||||
|
@ -118,7 +118,7 @@ export const decorateWithTableResult = (data: ExplorePanelData): Observable<Expl
|
||||
field.display ??
|
||||
getDisplayProcessor({
|
||||
field,
|
||||
theme: config.theme,
|
||||
theme: config.theme2,
|
||||
timeZone: data.request?.timezone ?? 'browser',
|
||||
});
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ import {
|
||||
DataFrame,
|
||||
getFieldDisplayValuesProxy,
|
||||
} from '@grafana/data';
|
||||
import { config, getTemplateSrv } from '@grafana/runtime';
|
||||
import { getTemplateSrv } from '@grafana/runtime';
|
||||
import { SplitOpen } from 'app/types/explore';
|
||||
import { getLinkSrv } from '../../panel/panellinks/link_srv';
|
||||
|
||||
@ -43,8 +43,9 @@ export const getFieldLinksForExplore = (options: {
|
||||
value: {
|
||||
name: dataFrame.name,
|
||||
refId: dataFrame.refId,
|
||||
fields: getFieldDisplayValuesProxy(dataFrame, rowIndex, {
|
||||
theme: config.theme,
|
||||
fields: getFieldDisplayValuesProxy({
|
||||
frame: dataFrame,
|
||||
rowIndex,
|
||||
}),
|
||||
},
|
||||
text: 'Data',
|
||||
|
@ -149,7 +149,7 @@ export class InspectDataTab extends PureComponent<Props, State> {
|
||||
// That's because transformers create new fields and data frames, so i.e. display processor is no longer there
|
||||
return applyFieldOverrides({
|
||||
data,
|
||||
theme: config.theme,
|
||||
theme: config.theme2,
|
||||
fieldConfig: panel.fieldConfig,
|
||||
replaceVariables: (value: string) => {
|
||||
return value;
|
||||
|
@ -3,12 +3,11 @@ import {
|
||||
FieldType,
|
||||
formattedValueToString,
|
||||
getDisplayProcessor,
|
||||
GrafanaTheme,
|
||||
GrafanaThemeV2,
|
||||
QueryResultMetaStat,
|
||||
TimeZone,
|
||||
} from '@grafana/data';
|
||||
import { config } from 'app/core/config';
|
||||
import { stylesFactory, useTheme } from '@grafana/ui';
|
||||
import { stylesFactory, useTheme2 } from '@grafana/ui';
|
||||
import { css } from '@emotion/css';
|
||||
|
||||
interface InspectStatsTableProps {
|
||||
@ -18,7 +17,7 @@ interface InspectStatsTableProps {
|
||||
}
|
||||
|
||||
export const InspectStatsTable: React.FC<InspectStatsTableProps> = ({ timeZone, name, stats }) => {
|
||||
const theme = useTheme();
|
||||
const theme = useTheme2();
|
||||
const styles = getStyles(theme);
|
||||
|
||||
if (!stats || !stats.length) {
|
||||
@ -34,7 +33,7 @@ export const InspectStatsTable: React.FC<InspectStatsTableProps> = ({ timeZone,
|
||||
return (
|
||||
<tr key={`${stat.displayName}-${index}`}>
|
||||
<td>{stat.displayName}</td>
|
||||
<td className={styles.cell}>{formatStat(stat, timeZone)}</td>
|
||||
<td className={styles.cell}>{formatStat(stat, timeZone, theme)}</td>
|
||||
</tr>
|
||||
);
|
||||
})}
|
||||
@ -44,22 +43,22 @@ export const InspectStatsTable: React.FC<InspectStatsTableProps> = ({ timeZone,
|
||||
);
|
||||
};
|
||||
|
||||
function formatStat(stat: QueryResultMetaStat, timeZone?: TimeZone): string {
|
||||
function formatStat(stat: QueryResultMetaStat, timeZone: TimeZone, theme: GrafanaThemeV2): string {
|
||||
const display = getDisplayProcessor({
|
||||
field: {
|
||||
type: FieldType.number,
|
||||
config: stat,
|
||||
},
|
||||
theme: config.theme,
|
||||
theme,
|
||||
timeZone,
|
||||
});
|
||||
return formattedValueToString(display(stat.value));
|
||||
}
|
||||
|
||||
const getStyles = stylesFactory((theme: GrafanaTheme) => {
|
||||
const getStyles = stylesFactory((theme: GrafanaThemeV2) => {
|
||||
return {
|
||||
wrapper: css`
|
||||
padding-bottom: ${theme.spacing.md};
|
||||
padding-bottom: ${theme.spacing(2)};
|
||||
`,
|
||||
cell: css`
|
||||
text-align: right;
|
||||
|
@ -1,11 +1,11 @@
|
||||
import React, { useState, useMemo } from 'react';
|
||||
import { applyFieldOverrides, FieldConfigSource, getTimeZone, PanelData, PanelPlugin } from '@grafana/data';
|
||||
import { PanelRendererProps } from '@grafana/runtime';
|
||||
import { config } from 'app/core/config';
|
||||
import { appEvents } from 'app/core/core';
|
||||
import { useAsync } from 'react-use';
|
||||
import { getPanelOptionsWithDefaults, OptionDefaults } from '../dashboard/state/getPanelOptionsWithDefaults';
|
||||
import { importPanelPlugin } from '../plugins/plugin_loader';
|
||||
import { useTheme2 } from '@grafana/ui';
|
||||
|
||||
export function PanelRenderer<P extends object = any, F extends object = any>(props: PanelRendererProps<P, F>) {
|
||||
const {
|
||||
@ -94,6 +94,7 @@ const useFieldOverrides = (
|
||||
const fieldConfig = defaultOptions?.fieldConfig;
|
||||
const series = data?.series;
|
||||
const fieldConfigRegistry = plugin?.fieldConfigRegistry;
|
||||
const theme = useTheme2();
|
||||
|
||||
return useMemo(() => {
|
||||
if (!fieldConfigRegistry || !fieldConfig || !data) {
|
||||
@ -107,9 +108,9 @@ const useFieldOverrides = (
|
||||
fieldConfig,
|
||||
fieldConfigRegistry,
|
||||
replaceVariables: (str: string) => str,
|
||||
theme: config.theme,
|
||||
theme,
|
||||
timeZone,
|
||||
}),
|
||||
};
|
||||
}, [fieldConfigRegistry, fieldConfig, data, series, timeZone]);
|
||||
}, [fieldConfigRegistry, fieldConfig, data, series, timeZone, theme]);
|
||||
};
|
||||
|
@ -1,9 +1,8 @@
|
||||
import { getFieldLinksSupplier } from './linkSuppliers';
|
||||
import { applyFieldOverrides, DataFrameView, dateTime, FieldDisplay, toDataFrame } from '@grafana/data';
|
||||
import { applyFieldOverrides, createTheme, DataFrameView, dateTime, FieldDisplay, toDataFrame } from '@grafana/data';
|
||||
import { getLinkSrv, LinkService, LinkSrv, setLinkSrv } from './link_srv';
|
||||
import { TemplateSrv } from '../../templating/template_srv';
|
||||
import { TimeSrv } from '../../dashboard/services/TimeSrv';
|
||||
import { getTheme } from '@grafana/ui';
|
||||
|
||||
describe('getFieldLinksSupplier', () => {
|
||||
let originalLinkSrv: LinkService;
|
||||
@ -93,7 +92,7 @@ describe('getFieldLinksSupplier', () => {
|
||||
},
|
||||
replaceVariables: (val: string) => val,
|
||||
timeZone: 'utc',
|
||||
theme: getTheme(),
|
||||
theme: createTheme(),
|
||||
})[0];
|
||||
|
||||
const rowIndex = 0;
|
||||
|
@ -13,7 +13,6 @@ import {
|
||||
ScopedVars,
|
||||
} from '@grafana/data';
|
||||
import { getLinkSrv } from './link_srv';
|
||||
import { config } from 'app/core/config';
|
||||
|
||||
interface SeriesVars {
|
||||
name?: string;
|
||||
@ -100,8 +99,9 @@ export const getFieldLinksSupplier = (value: FieldDisplay): LinkModelSupplier<Fi
|
||||
value: {
|
||||
name: dataFrame.name,
|
||||
refId: dataFrame.refId,
|
||||
fields: getFieldDisplayValuesProxy(dataFrame, value.rowIndex!, {
|
||||
theme: config.theme,
|
||||
fields: getFieldDisplayValuesProxy({
|
||||
frame: dataFrame,
|
||||
rowIndex: value.rowIndex!,
|
||||
}),
|
||||
},
|
||||
text: 'Data',
|
||||
|
@ -248,7 +248,7 @@ describe('PanelQueryRunner', () => {
|
||||
overrides: [],
|
||||
},
|
||||
replaceVariables: (v) => v,
|
||||
theme: {} as grafanaData.GrafanaTheme,
|
||||
theme: grafanaData.createTheme(),
|
||||
}),
|
||||
getTransformations: () => undefined,
|
||||
}
|
||||
@ -312,7 +312,7 @@ describe('PanelQueryRunner', () => {
|
||||
overrides: [],
|
||||
},
|
||||
replaceVariables: (v) => v,
|
||||
theme: {} as grafanaData.GrafanaTheme,
|
||||
theme: grafanaData.createTheme(),
|
||||
}),
|
||||
// @ts-ignore
|
||||
getTransformations: () => [({} as unknown) as grafanaData.DataTransformerConfig],
|
||||
@ -354,7 +354,7 @@ describe('PanelQueryRunner', () => {
|
||||
overrides: [],
|
||||
},
|
||||
replaceVariables: (v) => v,
|
||||
theme: {} as grafanaData.GrafanaTheme,
|
||||
theme: grafanaData.createTheme(),
|
||||
}),
|
||||
// @ts-ignore
|
||||
getTransformations: () => [{}],
|
||||
|
@ -103,7 +103,7 @@ export function getDefaultState(): State {
|
||||
overrides: [],
|
||||
},
|
||||
replaceVariables: (v: string) => v,
|
||||
theme: config.theme,
|
||||
theme: config.theme2,
|
||||
};
|
||||
|
||||
const dataConfig = {
|
||||
|
@ -40,7 +40,7 @@ export class BarGaugePanel extends PureComponent<PanelProps<BarGaugeOptions>> {
|
||||
field={field}
|
||||
text={options.text}
|
||||
display={processor}
|
||||
theme={config.theme}
|
||||
theme={config.theme2}
|
||||
itemSpacing={this.getItemSpacing()}
|
||||
displayMode={options.displayMode}
|
||||
onClick={openMenu}
|
||||
@ -73,7 +73,7 @@ export class BarGaugePanel extends PureComponent<PanelProps<BarGaugeOptions>> {
|
||||
fieldConfig,
|
||||
reduceOptions: options.reduceOptions,
|
||||
replaceVariables,
|
||||
theme: config.theme,
|
||||
theme: config.theme2,
|
||||
data: data.series,
|
||||
timeZone,
|
||||
});
|
||||
|
@ -56,7 +56,7 @@ export class GaugePanel extends PureComponent<PanelProps<GaugeOptions>> {
|
||||
fieldConfig,
|
||||
reduceOptions: options.reduceOptions,
|
||||
replaceVariables,
|
||||
theme: config.theme,
|
||||
theme: config.theme2,
|
||||
data: data.series,
|
||||
timeZone,
|
||||
});
|
||||
|
@ -286,7 +286,7 @@ class GraphElement {
|
||||
};
|
||||
const fieldDisplay = getDisplayProcessor({
|
||||
field: { config: fieldConfig, type: FieldType.number },
|
||||
theme: config.theme,
|
||||
theme: config.theme2,
|
||||
timeZone: this.dashboard.getTimezone(),
|
||||
})(field.values.get(dataIndex));
|
||||
linksSupplier = links.length
|
||||
|
@ -188,7 +188,7 @@ export class LivePanel extends PureComponent<Props, State> {
|
||||
const data: PanelData = {
|
||||
series: applyFieldOverrides({
|
||||
data: [message],
|
||||
theme: config.theme,
|
||||
theme: config.theme2,
|
||||
replaceVariables: (v: string) => v,
|
||||
fieldConfig: {
|
||||
defaults: {},
|
||||
|
@ -45,7 +45,7 @@ export class StatPanel extends PureComponent<PanelProps<StatPanelOptions>> {
|
||||
text={options.text}
|
||||
width={width}
|
||||
height={height}
|
||||
theme={config.theme}
|
||||
theme={config.theme2}
|
||||
onClick={openMenu}
|
||||
className={targetClassName}
|
||||
/>
|
||||
@ -87,7 +87,7 @@ export class StatPanel extends PureComponent<PanelProps<StatPanelOptions>> {
|
||||
fieldConfig,
|
||||
reduceOptions: options.reduceOptions,
|
||||
replaceVariables,
|
||||
theme: config.theme,
|
||||
theme: config.theme2,
|
||||
data: data.series,
|
||||
sparkline: options.graphMode !== BigValueGraphMode.None,
|
||||
timeZone,
|
||||
|
@ -14,7 +14,6 @@ import {
|
||||
CartesianCoords2D,
|
||||
DataFrame,
|
||||
DataFrameView,
|
||||
getDisplayProcessor,
|
||||
getFieldDisplayName,
|
||||
InterpolateFunction,
|
||||
TimeZone,
|
||||
@ -198,7 +197,7 @@ export const ContextMenuView: React.FC<ContextMenuProps> = ({
|
||||
|
||||
if (selection.point) {
|
||||
const { seriesIdx, dataIdx } = selection.point;
|
||||
const xFieldFmt = xField.display || getDisplayProcessor({ field: xField, timeZone });
|
||||
const xFieldFmt = xField.display!;
|
||||
|
||||
if (seriesIdx && dataIdx) {
|
||||
const field = data.fields[seriesIdx];
|
||||
|
Loading…
Reference in New Issue
Block a user