diff --git a/packages/grafana-data/src/field/displayProcessor.test.ts b/packages/grafana-data/src/field/displayProcessor.test.ts index 261e15bf8d6..19847215ca8 100644 --- a/packages/grafana-data/src/field/displayProcessor.test.ts +++ b/packages/grafana-data/src/field/displayProcessor.test.ts @@ -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'); }); diff --git a/packages/grafana-data/src/field/displayProcessor.ts b/packages/grafana-data/src/field/displayProcessor.ts index bd538320090..08a180af03c 100644 --- a/packages/grafana-data/src/field/displayProcessor.ts +++ b/packages/grafana-data/src/field/displayProcessor.ts @@ -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; @@ -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; diff --git a/packages/grafana-data/src/field/fieldColor.test.ts b/packages/grafana-data/src/field/fieldColor.test.ts index 295e71af681..6509d8c2dcb 100644 --- a/packages/grafana-data/src/field/fieldColor.test.ts +++ b/packages/grafana-data/src/field/fieldColor.test.ts @@ -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)); diff --git a/packages/grafana-data/src/field/fieldColor.ts b/packages/grafana-data/src/field/fieldColor.ts index 3a44113a9d5..fb1514d2be4 100644 --- a/packages/grafana-data/src/field/fieldColor.ts +++ b/packages/grafana-data/src/field/fieldColor.ts @@ -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(() => { 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); }; } diff --git a/packages/grafana-data/src/field/fieldDisplay.test.ts b/packages/grafana-data/src/field/fieldDisplay.test.ts index 16353d5e2d1..f286de0fa4c 100644 --- a/packages/grafana-data/src/field/fieldDisplay.test.ts +++ b/packages/grafana-data/src/field/fieldDisplay.test.ts @@ -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 = {} overrides: [], defaults: {}, }, - theme: getTestTheme(), + theme: createTheme(), }; return merge(options, extend); diff --git a/packages/grafana-data/src/field/fieldDisplay.ts b/packages/grafana-data/src/field/fieldDisplay.ts index 34f17416c66..69de42e46cd 100644 --- a/packages/grafana-data/src/field/fieldDisplay.ts +++ b/packages/grafana-data/src/field/fieldDisplay.ts @@ -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; } diff --git a/packages/grafana-data/src/field/fieldOverrides.test.ts b/packages/grafana-data/src/field/fieldOverrides.test.ts index a94037f42d0..4b6f2b356f4 100644 --- a/packages/grafana-data/src/field/fieldOverrides.test.ts +++ b/packages/grafana-data/src/field/fieldOverrides.test.ts @@ -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); diff --git a/packages/grafana-data/src/field/fieldOverrides.ts b/packages/grafana-data/src/field/fieldOverrides.ts index 2cbb6e50384..c81cc7c4a35 100644 --- a/packages/grafana-data/src/field/fieldOverrides.ts +++ b/packages/grafana-data/src/field/fieldOverrides.ts @@ -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> => { 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: { diff --git a/packages/grafana-data/src/field/getFieldDisplayValuesProxy.test.tsx b/packages/grafana-data/src/field/getFieldDisplayValuesProxy.test.tsx index ab550e1af5a..010fdafd3ce 100644 --- a/packages/grafana-data/src/field/getFieldDisplayValuesProxy.test.tsx +++ b/packages/grafana-data/src/field/getFieldDisplayValuesProxy.test.tsx @@ -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(); }); diff --git a/packages/grafana-data/src/field/getFieldDisplayValuesProxy.ts b/packages/grafana-data/src/field/getFieldDisplayValuesProxy.ts index 7c9b55f2728..255cc7b5714 100644 --- a/packages/grafana-data/src/field/getFieldDisplayValuesProxy.ts +++ b/packages/grafana-data/src/field/getFieldDisplayValuesProxy.ts @@ -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 { +export function getFieldDisplayValuesProxy(options: { + frame: DataFrame; + rowIndex: number; + timeZone?: TimeZone; +}): Record { return new Proxy({} as Record, { 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; diff --git a/packages/grafana-data/src/field/scale.test.ts b/packages/grafana-data/src/field/scale.test.ts index 0d284da4648..fcfa5cbee5c 100644 --- a/packages/grafana-data/src/field/scale.test.ts +++ b/packages/grafana-data/src/field/scale.test.ts @@ -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], diff --git a/packages/grafana-data/src/field/scale.ts b/packages/grafana-data/src/field/scale.ts index 62280274224..0bb5d3a6702 100644 --- a/packages/grafana-data/src/field/scale.ts +++ b/packages/grafana-data/src/field/scale.ts @@ -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); diff --git a/packages/grafana-data/src/types/config.ts b/packages/grafana-data/src/types/config.ts index 9dae23642a3..84b7ff0905b 100644 --- a/packages/grafana-data/src/types/config.ts +++ b/packages/grafana-data/src/types/config.ts @@ -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; diff --git a/packages/grafana-data/src/types/fieldOverrides.ts b/packages/grafana-data/src/types/fieldOverrides.ts index 7fb339d7254..9027c746fe9 100644 --- a/packages/grafana-data/src/types/fieldOverrides.ts +++ b/packages/grafana-data/src/types/fieldOverrides.ts @@ -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; } diff --git a/packages/grafana-data/src/utils/csv.test.ts b/packages/grafana-data/src/utils/csv.test.ts index 0d697064ae8..ea5f6598bf1 100644 --- a/packages/grafana-data/src/utils/csv.test.ts +++ b/packages/grafana-data/src/utils/csv.test.ts @@ -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(` diff --git a/packages/grafana-runtime/src/config.ts b/packages/grafana-runtime/src/config.ts index 3d2ab73ddaf..295710b530d 100644 --- a/packages/grafana-runtime/src/config.ts +++ b/packages/grafana-runtime/src/config.ts @@ -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: {}, diff --git a/packages/grafana-ui/src/components/BarChart/BarChart.story.tsx b/packages/grafana-ui/src/components/BarChart/BarChart.story.tsx index e3b2a3524eb..4deded449cb 100644 --- a/packages/grafana-ui/src/components/BarChart/BarChart.story.tsx +++ b/packages/grafana-ui/src/components/BarChart/BarChart.story.tsx @@ -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'] }, diff --git a/packages/grafana-ui/src/components/BarChart/BarChart.tsx b/packages/grafana-ui/src/components/BarChart/BarChart.tsx index 170e899d0a5..a2d69184d85 100644 --- a/packages/grafana-ui/src/components/BarChart/BarChart.tsx +++ b/packages/grafana-ui/src/components/BarChart/BarChart.tsx @@ -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 { } } -export const BarChart = withTheme(UnthemedBarChart); +export const BarChart = withTheme2(UnthemedBarChart); BarChart.displayName = 'GraphNG'; diff --git a/packages/grafana-ui/src/components/BarChart/__snapshots__/utils.test.ts.snap b/packages/grafana-ui/src/components/BarChart/__snapshots__/utils.test.ts.snap index c2198ef3437..c8bc16d13e0 100644 --- a/packages/grafana-ui/src/components/BarChart/__snapshots__/utils.test.ts.snap +++ b/packages/grafana-ui/src/components/BarChart/__snapshots__/utils.test.ts.snap @@ -1,50 +1,74 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`GraphNG utils preparePlotConfigBuilder orientation 1`] = ` -UPlotConfigBuilder { - "axes": Object { - "m/s": UPlotAxisBuilder { - "props": Object { - "formatValue": [Function], - "label": undefined, - "placement": "bottom", - "scaleKey": "m/s", - "size": undefined, - "theme": Object { - "colors": Object { - "panelBg": "#000000", - }, - }, +Object { + "axes": Array [ + Object { + "font": "12px \\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "gap": 15, + "grid": Object { + "show": false, + "stroke": "rgba(240, 250, 255, 0.09)", + "width": 1, }, - }, - "x": UPlotAxisBuilder { - "props": Object { - "gap": 15, - "grid": false, - "isTime": false, - "placement": "left", - "scaleKey": "x", - "splits": [Function], - "theme": Object { - "colors": Object { - "panelBg": "#000000", - }, - }, - "ticks": false, - "values": [Function], + "labelFont": "12px \\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "scale": "x", + "show": true, + "side": 3, + "size": [Function], + "space": [Function], + "splits": [Function], + "stroke": "rgb(201, 209, 217)", + "ticks": Object { + "show": false, + "stroke": "rgba(240, 250, 255, 0.09)", + "width": 1, }, + "timeZone": undefined, + "values": [Function], }, - }, - "bands": Array [], + 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": "m/s", + "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": undefined, + "values": [Function], + }, + ], "cursor": Object { + "drag": Object { + "setScale": false, + }, + "focus": Object { + "prox": 30, + }, "points": Object { + "fill": [Function], "show": false, + "size": [Function], + "stroke": [Function], + "width": [Function], }, "x": false, "y": false, }, - "hasBottomAxis": true, - "hasLeftAxis": true, "hooks": Object { "drawClear": Array [ [Function], @@ -56,116 +80,121 @@ UPlotConfigBuilder { [Function], ], }, - "isStacking": false, - "scales": Array [ - UPlotScaleBuilder { - "props": Object { - "direction": -1, - "distribution": "ordinal", - "isTime": false, - "orientation": 1, - "scaleKey": "x", - }, + "scales": Object { + "m/s": Object { + "auto": true, + "dir": 1, + "distr": 1, + "log": undefined, + "ori": 0, + "range": [Function], + "time": undefined, }, - UPlotScaleBuilder { - "props": Object { - "direction": 1, - "max": undefined, - "min": undefined, - "orientation": 0, - "scaleKey": "m/s", - "softMax": undefined, - "softMin": 0, - }, + "x": Object { + "auto": true, + "dir": -1, + "distr": 2, + "log": undefined, + "ori": 1, + "range": [Function], + "time": false, }, - ], + }, "select": Object { "show": false, }, "series": Array [ - UPlotSeriesBuilder { - "props": Object { - "colorMode": Object { - "description": "Derive colors from thresholds", - "getCalculator": [Function], - "id": "thresholds", - "isByValue": true, - "name": "From thresholds", - }, - "dataFrameFieldIndex": Object { - "fieldIndex": 1, - "frameIndex": 0, - }, - "fieldName": "Metric 1", - "fillOpacity": 0.1, - "gradientMode": "opacity", - "hideInLegend": undefined, - "lineColor": "#808080", - "lineWidth": 2, - "pathBuilder": [Function], - "pointsBuilder": [Function], - "pxAlign": false, - "scaleKey": "m/s", - "show": true, - "theme": Object { - "colors": Object { - "panelBg": "#000000", - }, - }, - "thresholds": undefined, + Object {}, + Object { + "fill": [Function], + "paths": [Function], + "points": Object { + "fill": undefined, + "show": [Function], + "size": undefined, + "stroke": undefined, }, + "pxAlign": false, + "scale": "m/s", + "show": true, + "spanGaps": undefined, + "stroke": "#808080", + "width": 2, }, ], - "tz": "UTC", "tzDate": [Function], } `; exports[`GraphNG utils preparePlotConfigBuilder orientation 2`] = ` -UPlotConfigBuilder { - "axes": Object { - "m/s": UPlotAxisBuilder { - "props": Object { - "formatValue": [Function], - "label": undefined, - "placement": "bottom", - "scaleKey": "m/s", - "size": undefined, - "theme": Object { - "colors": Object { - "panelBg": "#000000", - }, - }, +Object { + "axes": Array [ + Object { + "font": "12px \\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "gap": 15, + "grid": Object { + "show": false, + "stroke": "rgba(240, 250, 255, 0.09)", + "width": 1, }, - }, - "x": UPlotAxisBuilder { - "props": Object { - "gap": 15, - "grid": false, - "isTime": false, - "placement": "left", - "scaleKey": "x", - "splits": [Function], - "theme": Object { - "colors": Object { - "panelBg": "#000000", - }, - }, - "ticks": false, - "values": [Function], + "labelFont": "12px \\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "scale": "x", + "show": true, + "side": 3, + "size": [Function], + "space": [Function], + "splits": [Function], + "stroke": "rgb(201, 209, 217)", + "ticks": Object { + "show": false, + "stroke": "rgba(240, 250, 255, 0.09)", + "width": 1, }, + "timeZone": undefined, + "values": [Function], }, - }, - "bands": Array [], + 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": "m/s", + "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": undefined, + "values": [Function], + }, + ], "cursor": Object { + "drag": Object { + "setScale": false, + }, + "focus": Object { + "prox": 30, + }, "points": Object { + "fill": [Function], "show": false, + "size": [Function], + "stroke": [Function], + "width": [Function], }, "x": false, "y": false, }, - "hasBottomAxis": true, - "hasLeftAxis": true, "hooks": Object { "drawClear": Array [ [Function], @@ -177,116 +206,121 @@ UPlotConfigBuilder { [Function], ], }, - "isStacking": false, - "scales": Array [ - UPlotScaleBuilder { - "props": Object { - "direction": -1, - "distribution": "ordinal", - "isTime": false, - "orientation": 1, - "scaleKey": "x", - }, + "scales": Object { + "m/s": Object { + "auto": true, + "dir": 1, + "distr": 1, + "log": undefined, + "ori": 0, + "range": [Function], + "time": undefined, }, - UPlotScaleBuilder { - "props": Object { - "direction": 1, - "max": undefined, - "min": undefined, - "orientation": 0, - "scaleKey": "m/s", - "softMax": undefined, - "softMin": 0, - }, + "x": Object { + "auto": true, + "dir": -1, + "distr": 2, + "log": undefined, + "ori": 1, + "range": [Function], + "time": false, }, - ], + }, "select": Object { "show": false, }, "series": Array [ - UPlotSeriesBuilder { - "props": Object { - "colorMode": Object { - "description": "Derive colors from thresholds", - "getCalculator": [Function], - "id": "thresholds", - "isByValue": true, - "name": "From thresholds", - }, - "dataFrameFieldIndex": Object { - "fieldIndex": 1, - "frameIndex": 0, - }, - "fieldName": "Metric 1", - "fillOpacity": 0.1, - "gradientMode": "opacity", - "hideInLegend": undefined, - "lineColor": "#808080", - "lineWidth": 2, - "pathBuilder": [Function], - "pointsBuilder": [Function], - "pxAlign": false, - "scaleKey": "m/s", - "show": true, - "theme": Object { - "colors": Object { - "panelBg": "#000000", - }, - }, - "thresholds": undefined, + Object {}, + Object { + "fill": [Function], + "paths": [Function], + "points": Object { + "fill": undefined, + "show": [Function], + "size": undefined, + "stroke": undefined, }, + "pxAlign": false, + "scale": "m/s", + "show": true, + "spanGaps": undefined, + "stroke": "#808080", + "width": 2, }, ], - "tz": "UTC", "tzDate": [Function], } `; exports[`GraphNG utils preparePlotConfigBuilder orientation 3`] = ` -UPlotConfigBuilder { - "axes": Object { - "m/s": UPlotAxisBuilder { - "props": Object { - "formatValue": [Function], - "label": undefined, - "placement": "left", - "scaleKey": "m/s", - "size": undefined, - "theme": Object { - "colors": Object { - "panelBg": "#000000", - }, - }, +Object { + "axes": Array [ + Object { + "font": "12px \\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "gap": 15, + "grid": Object { + "show": false, + "stroke": "rgba(240, 250, 255, 0.09)", + "width": 1, }, - }, - "x": UPlotAxisBuilder { - "props": Object { - "gap": 15, - "grid": false, - "isTime": false, - "placement": "bottom", - "scaleKey": "x", - "splits": [Function], - "theme": Object { - "colors": Object { - "panelBg": "#000000", - }, - }, - "ticks": false, - "values": [Function], + "labelFont": "12px \\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "scale": "x", + "show": true, + "side": 2, + "size": [Function], + "space": [Function], + "splits": [Function], + "stroke": "rgb(201, 209, 217)", + "ticks": Object { + "show": false, + "stroke": "rgba(240, 250, 255, 0.09)", + "width": 1, }, + "timeZone": undefined, + "values": [Function], }, - }, - "bands": Array [], + 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": "m/s", + "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], + }, + ], "cursor": Object { + "drag": Object { + "setScale": false, + }, + "focus": Object { + "prox": 30, + }, "points": Object { + "fill": [Function], "show": false, + "size": [Function], + "stroke": [Function], + "width": [Function], }, "x": false, "y": false, }, - "hasBottomAxis": true, - "hasLeftAxis": true, "hooks": Object { "drawClear": Array [ [Function], @@ -298,116 +332,121 @@ UPlotConfigBuilder { [Function], ], }, - "isStacking": false, - "scales": Array [ - UPlotScaleBuilder { - "props": Object { - "direction": 1, - "distribution": "ordinal", - "isTime": false, - "orientation": 0, - "scaleKey": "x", - }, + "scales": Object { + "m/s": Object { + "auto": true, + "dir": 1, + "distr": 1, + "log": undefined, + "ori": 1, + "range": [Function], + "time": undefined, }, - UPlotScaleBuilder { - "props": Object { - "direction": 1, - "max": undefined, - "min": undefined, - "orientation": 1, - "scaleKey": "m/s", - "softMax": undefined, - "softMin": 0, - }, + "x": Object { + "auto": true, + "dir": 1, + "distr": 2, + "log": undefined, + "ori": 0, + "range": [Function], + "time": false, }, - ], + }, "select": Object { "show": false, }, "series": Array [ - UPlotSeriesBuilder { - "props": Object { - "colorMode": Object { - "description": "Derive colors from thresholds", - "getCalculator": [Function], - "id": "thresholds", - "isByValue": true, - "name": "From thresholds", - }, - "dataFrameFieldIndex": Object { - "fieldIndex": 1, - "frameIndex": 0, - }, - "fieldName": "Metric 1", - "fillOpacity": 0.1, - "gradientMode": "opacity", - "hideInLegend": undefined, - "lineColor": "#808080", - "lineWidth": 2, - "pathBuilder": [Function], - "pointsBuilder": [Function], - "pxAlign": false, - "scaleKey": "m/s", - "show": true, - "theme": Object { - "colors": Object { - "panelBg": "#000000", - }, - }, - "thresholds": undefined, + Object {}, + Object { + "fill": [Function], + "paths": [Function], + "points": Object { + "fill": undefined, + "show": [Function], + "size": undefined, + "stroke": undefined, }, + "pxAlign": false, + "scale": "m/s", + "show": true, + "spanGaps": undefined, + "stroke": "#808080", + "width": 2, }, ], - "tz": "UTC", "tzDate": [Function], } `; exports[`GraphNG utils preparePlotConfigBuilder stacking 1`] = ` -UPlotConfigBuilder { - "axes": Object { - "m/s": UPlotAxisBuilder { - "props": Object { - "formatValue": [Function], - "label": undefined, - "placement": "bottom", - "scaleKey": "m/s", - "size": undefined, - "theme": Object { - "colors": Object { - "panelBg": "#000000", - }, - }, +Object { + "axes": Array [ + Object { + "font": "12px \\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "gap": 15, + "grid": Object { + "show": false, + "stroke": "rgba(240, 250, 255, 0.09)", + "width": 1, }, - }, - "x": UPlotAxisBuilder { - "props": Object { - "gap": 15, - "grid": false, - "isTime": false, - "placement": "left", - "scaleKey": "x", - "splits": [Function], - "theme": Object { - "colors": Object { - "panelBg": "#000000", - }, - }, - "ticks": false, - "values": [Function], + "labelFont": "12px \\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "scale": "x", + "show": true, + "side": 3, + "size": [Function], + "space": [Function], + "splits": [Function], + "stroke": "rgb(201, 209, 217)", + "ticks": Object { + "show": false, + "stroke": "rgba(240, 250, 255, 0.09)", + "width": 1, }, + "timeZone": undefined, + "values": [Function], }, - }, - "bands": Array [], + 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": "m/s", + "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": undefined, + "values": [Function], + }, + ], "cursor": Object { + "drag": Object { + "setScale": false, + }, + "focus": Object { + "prox": 30, + }, "points": Object { + "fill": [Function], "show": false, + "size": [Function], + "stroke": [Function], + "width": [Function], }, "x": false, "y": false, }, - "hasBottomAxis": true, - "hasLeftAxis": true, "hooks": Object { "drawClear": Array [ [Function], @@ -419,116 +458,121 @@ UPlotConfigBuilder { [Function], ], }, - "isStacking": false, - "scales": Array [ - UPlotScaleBuilder { - "props": Object { - "direction": -1, - "distribution": "ordinal", - "isTime": false, - "orientation": 1, - "scaleKey": "x", - }, + "scales": Object { + "m/s": Object { + "auto": true, + "dir": 1, + "distr": 1, + "log": undefined, + "ori": 0, + "range": [Function], + "time": undefined, }, - UPlotScaleBuilder { - "props": Object { - "direction": 1, - "max": undefined, - "min": undefined, - "orientation": 0, - "scaleKey": "m/s", - "softMax": undefined, - "softMin": 0, - }, + "x": Object { + "auto": true, + "dir": -1, + "distr": 2, + "log": undefined, + "ori": 1, + "range": [Function], + "time": false, }, - ], + }, "select": Object { "show": false, }, "series": Array [ - UPlotSeriesBuilder { - "props": Object { - "colorMode": Object { - "description": "Derive colors from thresholds", - "getCalculator": [Function], - "id": "thresholds", - "isByValue": true, - "name": "From thresholds", - }, - "dataFrameFieldIndex": Object { - "fieldIndex": 1, - "frameIndex": 0, - }, - "fieldName": "Metric 1", - "fillOpacity": 0.1, - "gradientMode": "opacity", - "hideInLegend": undefined, - "lineColor": "#808080", - "lineWidth": 2, - "pathBuilder": [Function], - "pointsBuilder": [Function], - "pxAlign": false, - "scaleKey": "m/s", - "show": true, - "theme": Object { - "colors": Object { - "panelBg": "#000000", - }, - }, - "thresholds": undefined, + Object {}, + Object { + "fill": [Function], + "paths": [Function], + "points": Object { + "fill": undefined, + "show": [Function], + "size": undefined, + "stroke": undefined, }, + "pxAlign": false, + "scale": "m/s", + "show": true, + "spanGaps": undefined, + "stroke": "#808080", + "width": 2, }, ], - "tz": "UTC", "tzDate": [Function], } `; exports[`GraphNG utils preparePlotConfigBuilder stacking 2`] = ` -UPlotConfigBuilder { - "axes": Object { - "m/s": UPlotAxisBuilder { - "props": Object { - "formatValue": [Function], - "label": undefined, - "placement": "bottom", - "scaleKey": "m/s", - "size": undefined, - "theme": Object { - "colors": Object { - "panelBg": "#000000", - }, - }, +Object { + "axes": Array [ + Object { + "font": "12px \\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "gap": 15, + "grid": Object { + "show": false, + "stroke": "rgba(240, 250, 255, 0.09)", + "width": 1, }, - }, - "x": UPlotAxisBuilder { - "props": Object { - "gap": 15, - "grid": false, - "isTime": false, - "placement": "left", - "scaleKey": "x", - "splits": [Function], - "theme": Object { - "colors": Object { - "panelBg": "#000000", - }, - }, - "ticks": false, - "values": [Function], + "labelFont": "12px \\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "scale": "x", + "show": true, + "side": 3, + "size": [Function], + "space": [Function], + "splits": [Function], + "stroke": "rgb(201, 209, 217)", + "ticks": Object { + "show": false, + "stroke": "rgba(240, 250, 255, 0.09)", + "width": 1, }, + "timeZone": undefined, + "values": [Function], }, - }, - "bands": Array [], + 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": "m/s", + "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": undefined, + "values": [Function], + }, + ], "cursor": Object { + "drag": Object { + "setScale": false, + }, + "focus": Object { + "prox": 30, + }, "points": Object { + "fill": [Function], "show": false, + "size": [Function], + "stroke": [Function], + "width": [Function], }, "x": false, "y": false, }, - "hasBottomAxis": true, - "hasLeftAxis": true, "hooks": Object { "drawClear": Array [ [Function], @@ -540,116 +584,121 @@ UPlotConfigBuilder { [Function], ], }, - "isStacking": false, - "scales": Array [ - UPlotScaleBuilder { - "props": Object { - "direction": -1, - "distribution": "ordinal", - "isTime": false, - "orientation": 1, - "scaleKey": "x", - }, + "scales": Object { + "m/s": Object { + "auto": true, + "dir": 1, + "distr": 1, + "log": undefined, + "ori": 0, + "range": [Function], + "time": undefined, }, - UPlotScaleBuilder { - "props": Object { - "direction": 1, - "max": undefined, - "min": undefined, - "orientation": 0, - "scaleKey": "m/s", - "softMax": undefined, - "softMin": 0, - }, + "x": Object { + "auto": true, + "dir": -1, + "distr": 2, + "log": undefined, + "ori": 1, + "range": [Function], + "time": false, }, - ], + }, "select": Object { "show": false, }, "series": Array [ - UPlotSeriesBuilder { - "props": Object { - "colorMode": Object { - "description": "Derive colors from thresholds", - "getCalculator": [Function], - "id": "thresholds", - "isByValue": true, - "name": "From thresholds", - }, - "dataFrameFieldIndex": Object { - "fieldIndex": 1, - "frameIndex": 0, - }, - "fieldName": "Metric 1", - "fillOpacity": 0.1, - "gradientMode": "opacity", - "hideInLegend": undefined, - "lineColor": "#808080", - "lineWidth": 2, - "pathBuilder": [Function], - "pointsBuilder": [Function], - "pxAlign": false, - "scaleKey": "m/s", - "show": true, - "theme": Object { - "colors": Object { - "panelBg": "#000000", - }, - }, - "thresholds": undefined, + Object {}, + Object { + "fill": [Function], + "paths": [Function], + "points": Object { + "fill": undefined, + "show": [Function], + "size": undefined, + "stroke": undefined, }, + "pxAlign": false, + "scale": "m/s", + "show": true, + "spanGaps": undefined, + "stroke": "#808080", + "width": 2, }, ], - "tz": "UTC", "tzDate": [Function], } `; exports[`GraphNG utils preparePlotConfigBuilder stacking 3`] = ` -UPlotConfigBuilder { - "axes": Object { - "m/s": UPlotAxisBuilder { - "props": Object { - "formatValue": [Function], - "label": undefined, - "placement": "bottom", - "scaleKey": "m/s", - "size": undefined, - "theme": Object { - "colors": Object { - "panelBg": "#000000", - }, - }, +Object { + "axes": Array [ + Object { + "font": "12px \\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "gap": 15, + "grid": Object { + "show": false, + "stroke": "rgba(240, 250, 255, 0.09)", + "width": 1, }, - }, - "x": UPlotAxisBuilder { - "props": Object { - "gap": 15, - "grid": false, - "isTime": false, - "placement": "left", - "scaleKey": "x", - "splits": [Function], - "theme": Object { - "colors": Object { - "panelBg": "#000000", - }, - }, - "ticks": false, - "values": [Function], + "labelFont": "12px \\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "scale": "x", + "show": true, + "side": 3, + "size": [Function], + "space": [Function], + "splits": [Function], + "stroke": "rgb(201, 209, 217)", + "ticks": Object { + "show": false, + "stroke": "rgba(240, 250, 255, 0.09)", + "width": 1, }, + "timeZone": undefined, + "values": [Function], }, - }, - "bands": Array [], + 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": "m/s", + "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": undefined, + "values": [Function], + }, + ], "cursor": Object { + "drag": Object { + "setScale": false, + }, + "focus": Object { + "prox": 30, + }, "points": Object { + "fill": [Function], "show": false, + "size": [Function], + "stroke": [Function], + "width": [Function], }, "x": false, "y": false, }, - "hasBottomAxis": true, - "hasLeftAxis": true, "hooks": Object { "drawClear": Array [ [Function], @@ -661,116 +710,121 @@ UPlotConfigBuilder { [Function], ], }, - "isStacking": false, - "scales": Array [ - UPlotScaleBuilder { - "props": Object { - "direction": -1, - "distribution": "ordinal", - "isTime": false, - "orientation": 1, - "scaleKey": "x", - }, + "scales": Object { + "m/s": Object { + "auto": true, + "dir": 1, + "distr": 1, + "log": undefined, + "ori": 0, + "range": [Function], + "time": undefined, }, - UPlotScaleBuilder { - "props": Object { - "direction": 1, - "max": undefined, - "min": undefined, - "orientation": 0, - "scaleKey": "m/s", - "softMax": undefined, - "softMin": 0, - }, + "x": Object { + "auto": true, + "dir": -1, + "distr": 2, + "log": undefined, + "ori": 1, + "range": [Function], + "time": false, }, - ], + }, "select": Object { "show": false, }, "series": Array [ - UPlotSeriesBuilder { - "props": Object { - "colorMode": Object { - "description": "Derive colors from thresholds", - "getCalculator": [Function], - "id": "thresholds", - "isByValue": true, - "name": "From thresholds", - }, - "dataFrameFieldIndex": Object { - "fieldIndex": 1, - "frameIndex": 0, - }, - "fieldName": "Metric 1", - "fillOpacity": 0.1, - "gradientMode": "opacity", - "hideInLegend": undefined, - "lineColor": "#808080", - "lineWidth": 2, - "pathBuilder": [Function], - "pointsBuilder": [Function], - "pxAlign": false, - "scaleKey": "m/s", - "show": true, - "theme": Object { - "colors": Object { - "panelBg": "#000000", - }, - }, - "thresholds": undefined, + Object {}, + Object { + "fill": [Function], + "paths": [Function], + "points": Object { + "fill": undefined, + "show": [Function], + "size": undefined, + "stroke": undefined, }, + "pxAlign": false, + "scale": "m/s", + "show": true, + "spanGaps": undefined, + "stroke": "#808080", + "width": 2, }, ], - "tz": "UTC", "tzDate": [Function], } `; exports[`GraphNG utils preparePlotConfigBuilder value visibility 1`] = ` -UPlotConfigBuilder { - "axes": Object { - "m/s": UPlotAxisBuilder { - "props": Object { - "formatValue": [Function], - "label": undefined, - "placement": "bottom", - "scaleKey": "m/s", - "size": undefined, - "theme": Object { - "colors": Object { - "panelBg": "#000000", - }, - }, +Object { + "axes": Array [ + Object { + "font": "12px \\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "gap": 15, + "grid": Object { + "show": false, + "stroke": "rgba(240, 250, 255, 0.09)", + "width": 1, }, - }, - "x": UPlotAxisBuilder { - "props": Object { - "gap": 15, - "grid": false, - "isTime": false, - "placement": "left", - "scaleKey": "x", - "splits": [Function], - "theme": Object { - "colors": Object { - "panelBg": "#000000", - }, - }, - "ticks": false, - "values": [Function], + "labelFont": "12px \\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "scale": "x", + "show": true, + "side": 3, + "size": [Function], + "space": [Function], + "splits": [Function], + "stroke": "rgb(201, 209, 217)", + "ticks": Object { + "show": false, + "stroke": "rgba(240, 250, 255, 0.09)", + "width": 1, }, + "timeZone": undefined, + "values": [Function], }, - }, - "bands": Array [], + 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": "m/s", + "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": undefined, + "values": [Function], + }, + ], "cursor": Object { + "drag": Object { + "setScale": false, + }, + "focus": Object { + "prox": 30, + }, "points": Object { + "fill": [Function], "show": false, + "size": [Function], + "stroke": [Function], + "width": [Function], }, "x": false, "y": false, }, - "hasBottomAxis": true, - "hasLeftAxis": true, "hooks": Object { "drawClear": Array [ [Function], @@ -782,116 +836,121 @@ UPlotConfigBuilder { [Function], ], }, - "isStacking": false, - "scales": Array [ - UPlotScaleBuilder { - "props": Object { - "direction": -1, - "distribution": "ordinal", - "isTime": false, - "orientation": 1, - "scaleKey": "x", - }, + "scales": Object { + "m/s": Object { + "auto": true, + "dir": 1, + "distr": 1, + "log": undefined, + "ori": 0, + "range": [Function], + "time": undefined, }, - UPlotScaleBuilder { - "props": Object { - "direction": 1, - "max": undefined, - "min": undefined, - "orientation": 0, - "scaleKey": "m/s", - "softMax": undefined, - "softMin": 0, - }, + "x": Object { + "auto": true, + "dir": -1, + "distr": 2, + "log": undefined, + "ori": 1, + "range": [Function], + "time": false, }, - ], + }, "select": Object { "show": false, }, "series": Array [ - UPlotSeriesBuilder { - "props": Object { - "colorMode": Object { - "description": "Derive colors from thresholds", - "getCalculator": [Function], - "id": "thresholds", - "isByValue": true, - "name": "From thresholds", - }, - "dataFrameFieldIndex": Object { - "fieldIndex": 1, - "frameIndex": 0, - }, - "fieldName": "Metric 1", - "fillOpacity": 0.1, - "gradientMode": "opacity", - "hideInLegend": undefined, - "lineColor": "#808080", - "lineWidth": 2, - "pathBuilder": [Function], - "pointsBuilder": [Function], - "pxAlign": false, - "scaleKey": "m/s", - "show": true, - "theme": Object { - "colors": Object { - "panelBg": "#000000", - }, - }, - "thresholds": undefined, + Object {}, + Object { + "fill": [Function], + "paths": [Function], + "points": Object { + "fill": undefined, + "show": [Function], + "size": undefined, + "stroke": undefined, }, + "pxAlign": false, + "scale": "m/s", + "show": true, + "spanGaps": undefined, + "stroke": "#808080", + "width": 2, }, ], - "tz": "UTC", "tzDate": [Function], } `; exports[`GraphNG utils preparePlotConfigBuilder value visibility 2`] = ` -UPlotConfigBuilder { - "axes": Object { - "m/s": UPlotAxisBuilder { - "props": Object { - "formatValue": [Function], - "label": undefined, - "placement": "bottom", - "scaleKey": "m/s", - "size": undefined, - "theme": Object { - "colors": Object { - "panelBg": "#000000", - }, - }, +Object { + "axes": Array [ + Object { + "font": "12px \\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "gap": 15, + "grid": Object { + "show": false, + "stroke": "rgba(240, 250, 255, 0.09)", + "width": 1, }, - }, - "x": UPlotAxisBuilder { - "props": Object { - "gap": 15, - "grid": false, - "isTime": false, - "placement": "left", - "scaleKey": "x", - "splits": [Function], - "theme": Object { - "colors": Object { - "panelBg": "#000000", - }, - }, - "ticks": false, - "values": [Function], + "labelFont": "12px \\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "scale": "x", + "show": true, + "side": 3, + "size": [Function], + "space": [Function], + "splits": [Function], + "stroke": "rgb(201, 209, 217)", + "ticks": Object { + "show": false, + "stroke": "rgba(240, 250, 255, 0.09)", + "width": 1, }, + "timeZone": undefined, + "values": [Function], }, - }, - "bands": Array [], + 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": "m/s", + "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": undefined, + "values": [Function], + }, + ], "cursor": Object { + "drag": Object { + "setScale": false, + }, + "focus": Object { + "prox": 30, + }, "points": Object { + "fill": [Function], "show": false, + "size": [Function], + "stroke": [Function], + "width": [Function], }, "x": false, "y": false, }, - "hasBottomAxis": true, - "hasLeftAxis": true, "hooks": Object { "drawClear": Array [ [Function], @@ -903,67 +962,48 @@ UPlotConfigBuilder { [Function], ], }, - "isStacking": false, - "scales": Array [ - UPlotScaleBuilder { - "props": Object { - "direction": -1, - "distribution": "ordinal", - "isTime": false, - "orientation": 1, - "scaleKey": "x", - }, + "scales": Object { + "m/s": Object { + "auto": true, + "dir": 1, + "distr": 1, + "log": undefined, + "ori": 0, + "range": [Function], + "time": undefined, }, - UPlotScaleBuilder { - "props": Object { - "direction": 1, - "max": undefined, - "min": undefined, - "orientation": 0, - "scaleKey": "m/s", - "softMax": undefined, - "softMin": 0, - }, + "x": Object { + "auto": true, + "dir": -1, + "distr": 2, + "log": undefined, + "ori": 1, + "range": [Function], + "time": false, }, - ], + }, "select": Object { "show": false, }, "series": Array [ - UPlotSeriesBuilder { - "props": Object { - "colorMode": Object { - "description": "Derive colors from thresholds", - "getCalculator": [Function], - "id": "thresholds", - "isByValue": true, - "name": "From thresholds", - }, - "dataFrameFieldIndex": Object { - "fieldIndex": 1, - "frameIndex": 0, - }, - "fieldName": "Metric 1", - "fillOpacity": 0.1, - "gradientMode": "opacity", - "hideInLegend": undefined, - "lineColor": "#808080", - "lineWidth": 2, - "pathBuilder": [Function], - "pointsBuilder": [Function], - "pxAlign": false, - "scaleKey": "m/s", - "show": true, - "theme": Object { - "colors": Object { - "panelBg": "#000000", - }, - }, - "thresholds": undefined, + Object {}, + Object { + "fill": [Function], + "paths": [Function], + "points": Object { + "fill": undefined, + "show": [Function], + "size": undefined, + "stroke": undefined, }, + "pxAlign": false, + "scale": "m/s", + "show": true, + "spanGaps": undefined, + "stroke": "#808080", + "width": 2, }, ], - "tz": "UTC", "tzDate": [Function], } `; diff --git a/packages/grafana-ui/src/components/BarChart/utils.test.ts b/packages/grafana-ui/src/components/BarChart/utils.test.ts index be48c3bd599..fe485b440af 100644 --- a/packages/grafana-ui/src/components/BarChart/utils.test.ts +++ b/packages/grafana-ui/src/components/BarChart/utils.test.ts @@ -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(); }); }); diff --git a/packages/grafana-ui/src/components/BarChart/utils.ts b/packages/grafana-ui/src/components/BarChart/utils.ts index f5ae05ddbca..d8a917e9000 100644 --- a/packages/grafana-ui/src/components/BarChart/utils.ts +++ b/packages/grafana-ui/src/components/BarChart/utils.ts @@ -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(); diff --git a/packages/grafana-ui/src/components/BarGauge/BarGauge.story.tsx b/packages/grafana-ui/src/components/BarGauge/BarGauge.story.tsx index e468f881cb6..5d15a3826d4 100644 --- a/packages/grafana-ui/src/components/BarGauge/BarGauge.story.tsx +++ b/packages/grafana-ui/src/components/BarGauge/BarGauge.story.tsx @@ -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 { } const AddBarGaugeStory = (storyProps: StoryProps) => { - const theme = useTheme(); + const theme = useTheme2(); const field: Partial = { type: FieldType.number, @@ -89,7 +89,7 @@ const AddBarGaugeStory = (storyProps: StoryProps) => { }, }, }; - field.display = getDisplayProcessor({ field }); + field.display = getDisplayProcessor({ field, theme }); const props: Partial = { theme, diff --git a/packages/grafana-ui/src/components/BarGauge/BarGauge.test.tsx b/packages/grafana-ui/src/components/BarGauge/BarGauge.test.tsx index 7eaa5dbe45d..340845b1436 100644 --- a/packages/grafana-ui/src/components/BarGauge/BarGauge.test.tsx +++ b/packages/grafana-ui/src/components/BarGauge/BarGauge.test.tsx @@ -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 { }, }, }; - const theme = getTheme(); + const theme = createTheme(); field.display = getDisplayProcessor({ field, theme }); const props: Props = { diff --git a/packages/grafana-ui/src/components/BarGauge/BarGauge.tsx b/packages/grafana-ui/src/components/BarGauge/BarGauge.tsx index 712785d55ff..b7b19c63630 100644 --- a/packages/grafana-ui/src/components/BarGauge/BarGauge.tsx +++ b/packages/grafana-ui/src/components/BarGauge/BarGauge.tsx @@ -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]; diff --git a/packages/grafana-ui/src/components/BigValue/BigValue.story.tsx b/packages/grafana-ui/src/components/BigValue/BigValue.story.tsx index c11eb453c8d..88cff868cfb 100644 --- a/packages/grafana-ui/src/components/BigValue/BigValue.story.tsx +++ b/packages/grafana-ui/src/components/BigValue/BigValue.story.tsx @@ -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 = ({ textMode, justifyMode, }) => { - const theme = useTheme(); + const theme = useTheme2(); const sparkline: FieldSparkline = { y: { name: '', diff --git a/packages/grafana-ui/src/components/BigValue/BigValue.test.tsx b/packages/grafana-ui/src/components/BigValue/BigValue.test.tsx index a1acf460abb..eb140b59632 100644 --- a/packages/grafana-ui/src/components/BigValue/BigValue.test.tsx +++ b/packages/grafana-ui/src/components/BigValue/BigValue.test.tsx @@ -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 { const props: Props = { @@ -13,7 +13,7 @@ function getProps(propOverrides?: Partial): Props { text: '25', numeric: 25, }, - theme: getTheme(), + theme: createTheme(), }; Object.assign(props, propOverrides); diff --git a/packages/grafana-ui/src/components/BigValue/BigValue.tsx b/packages/grafana-ui/src/components/BigValue/BigValue.tsx index b9fa5417af4..24ed53c9c57 100644 --- a/packages/grafana-ui/src/components/BigValue/BigValue.tsx +++ b/packages/grafana-ui/src/components/BigValue/BigValue.tsx @@ -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 */ diff --git a/packages/grafana-ui/src/components/BigValue/BigValueLayout.test.tsx b/packages/grafana-ui/src/components/BigValue/BigValueLayout.test.tsx index b963b796ed2..9f311c98719 100644 --- a/packages/grafana-ui/src/components/BigValue/BigValueLayout.test.tsx +++ b/packages/grafana-ui/src/components/BigValue/BigValueLayout.test.tsx @@ -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 { const props: Props = { @@ -21,7 +20,7 @@ function getProps(propOverrides?: Partial): Props { config: {}, }, }, - theme: getTheme(), + theme: createTheme(), }; Object.assign(props, propOverrides); diff --git a/packages/grafana-ui/src/components/BigValue/BigValueLayout.tsx b/packages/grafana-ui/src/components/BigValue/BigValueLayout.tsx index 334406b4bac..e62987dfeb6 100644 --- a/packages/grafana-ui/src/components/BigValue/BigValueLayout.tsx +++ b/packages/grafana-ui/src/components/BigValue/BigValueLayout.tsx @@ -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); diff --git a/packages/grafana-ui/src/components/Graph/Graph.test.tsx b/packages/grafana-ui/src/components/Graph/Graph.test.tsx index 189f1d20583..2f73d620567 100644 --- a/packages/grafana-ui/src/components/Graph/Graph.test.tsx +++ b/packages/grafana-ui/src/components/Graph/Graph.test.tsx @@ -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: { diff --git a/packages/grafana-ui/src/components/Graph/GraphContextMenu.tsx b/packages/grafana-ui/src/components/Graph/GraphContextMenu.tsx index 26540fbe7e8..97677ea846e 100644 --- a/packages/grafana-ui/src/components/Graph/GraphContextMenu.tsx +++ b/packages/grafana-ui/src/components/Graph/GraphContextMenu.tsx @@ -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 = ({ 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); } diff --git a/packages/grafana-ui/src/components/Graph/GraphTooltip/MultiModeGraphTooltip.test.tsx b/packages/grafana-ui/src/components/Graph/GraphTooltip/MultiModeGraphTooltip.test.tsx index 64891a8bebe..067627d0380 100644 --- a/packages/grafana-ui/src/components/Graph/GraphTooltip/MultiModeGraphTooltip.test.tsx +++ b/packages/grafana-ui/src/components/Graph/GraphTooltip/MultiModeGraphTooltip.test.tsx @@ -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, }, ]), }; diff --git a/packages/grafana-ui/src/components/Graph/GraphTooltip/SingleModeGraphTooltip.tsx b/packages/grafana-ui/src/components/Graph/GraphTooltip/SingleModeGraphTooltip.tsx index a8834ac46bc..716fda9d34c 100644 --- a/packages/grafana-ui/src/components/Graph/GraphTooltip/SingleModeGraphTooltip.tsx +++ b/packages/grafana-ui/src/components/Graph/GraphTooltip/SingleModeGraphTooltip.tsx @@ -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 = ({ 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 ( diff --git a/packages/grafana-ui/src/components/Graph/utils.test.ts b/packages/grafana-ui/src/components/Graph/utils.test.ts index 4925ecac157..9f85d14237b 100644 --- a/packages/grafana-ui/src/components/Graph/utils.test.ts +++ b/packages/grafana-ui/src/components/Graph/utils.test.ts @@ -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); }); }); diff --git a/packages/grafana-ui/src/components/Graph/utils.ts b/packages/grafana-ui/src/components/Graph/utils.ts index 3bd1c858a49..51cc5b1e632 100644 --- a/packages/grafana-ui/src/components/Graph/utils.ts +++ b/packages/grafana-ui/src/components/Graph/utils.ts @@ -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), diff --git a/packages/grafana-ui/src/components/GraphNG/GraphNG.story.tsx b/packages/grafana-ui/src/components/GraphNG/GraphNG.story.tsx index 5141cf6a9db..a64616956f8 100644 --- a/packages/grafana-ui/src/components/GraphNG/GraphNG.story.tsx +++ b/packages/grafana-ui/src/components/GraphNG/GraphNG.story.tsx @@ -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 = ({ placement, unit, legendDisplayMode, ...args }) => { - const theme = useTheme(); + const theme = useTheme2(); const seriesA = toDataFrame({ target: 'SeriesA', datapoints: [ diff --git a/packages/grafana-ui/src/components/GraphNG/GraphNG.tsx b/packages/grafana-ui/src/components/GraphNG/GraphNG.tsx index b22294f7e8f..17f14a37a40 100755 --- a/packages/grafana-ui/src/components/GraphNG/GraphNG.tsx +++ b/packages/grafana-ui/src/components/GraphNG/GraphNG.tsx @@ -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 { } } -export const GraphNG = withTheme(UnthemedGraphNG); +export const GraphNG = withTheme2(UnthemedGraphNG); GraphNG.displayName = 'GraphNG'; diff --git a/packages/grafana-ui/src/components/GraphNG/__snapshots__/utils.test.ts.snap b/packages/grafana-ui/src/components/GraphNG/__snapshots__/utils.test.ts.snap index 8d65298a51a..7a535bc3ec7 100644 --- a/packages/grafana-ui/src/components/GraphNG/__snapshots__/utils.test.ts.snap +++ b/packages/grafana-ui/src/components/GraphNG/__snapshots__/utils.test.ts.snap @@ -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], } `; diff --git a/packages/grafana-ui/src/components/GraphNG/utils.test.ts b/packages/grafana-ui/src/components/GraphNG/utils.test.ts index 5e48b60693e..b3abfa83aef 100644 --- a/packages/grafana-ui/src/components/GraphNG/utils.test.ts +++ b/packages/grafana-ui/src/components/GraphNG/utils.test.ts @@ -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(); }); }); diff --git a/packages/grafana-ui/src/components/GraphNG/utils.ts b/packages/grafana-ui/src/components/GraphNG/utils.ts index bee32e510fa..e9e8036ac78 100644 --- a/packages/grafana-ui/src/components/GraphNG/utils.ts +++ b/packages/grafana-ui/src/components/GraphNG/utils.ts @@ -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 { diff --git a/packages/grafana-ui/src/components/NodeGraph/NodeGraph.tsx b/packages/grafana-ui/src/components/NodeGraph/NodeGraph.tsx index 5fa832f33a0..ec790646f54 100644 --- a/packages/grafana-ui/src/components/NodeGraph/NodeGraph.tsx +++ b/packages/grafana-ui/src/components/NodeGraph/NodeGraph.tsx @@ -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. diff --git a/packages/grafana-ui/src/components/NodeGraph/utils.test.ts b/packages/grafana-ui/src/components/NodeGraph/utils.test.ts index 5603fff9a0c..c0f7dbb7dba 100644 --- a/packages/grafana-ui/src/components/NodeGraph/utils.test.ts +++ b/packages/grafana-ui/src/components/NodeGraph/utils.test.ts @@ -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: [ diff --git a/packages/grafana-ui/src/components/NodeGraph/utils.ts b/packages/grafana-ui/src/components/NodeGraph/utils.ts index 067e51e242e..1326512b8d6 100644 --- a/packages/grafana-ui/src/components/NodeGraph/utils.ts +++ b/packages/grafana-ui/src/components/NodeGraph/utils.ts @@ -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); } diff --git a/packages/grafana-ui/src/components/PieChart/PieChart.tsx b/packages/grafana-ui/src/components/PieChart/PieChart.tsx index 3b3fd3cc50c..78cfe6b4f34 100644 --- a/packages/grafana-ui/src/components/PieChart/PieChart.tsx +++ b/packages/grafana-ui/src/components/PieChart/PieChart.tsx @@ -65,7 +65,7 @@ export function PieChart(props: PieChartProps) { fieldConfig, reduceOptions, data, - theme: theme.v1, + theme: theme, replaceVariables, timeZone, }); diff --git a/packages/grafana-ui/src/components/Sparkline/Sparkline.tsx b/packages/grafana-ui/src/components/Sparkline/Sparkline.tsx index 0f56730b32c..9e91b949630 100755 --- a/packages/grafana-ui/src/components/Sparkline/Sparkline.tsx +++ b/packages/grafana-ui/src/components/Sparkline/Sparkline.tsx @@ -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; @@ -144,6 +144,7 @@ export class Sparkline extends PureComponent { min: field.config.min, max: field.config.max, }); + builder.addAxis({ scaleKey, theme, diff --git a/packages/grafana-ui/src/components/Table/Table.story.tsx b/packages/grafana-ui/src/components/Table/Table.story.tsx index 1747def0e26..eaf87654f8b 100644 --- a/packages/grafana-ui/src/components/Table/Table.story.tsx +++ b/packages/grafana-ui/src/components/Table/Table.story.tsx @@ -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): DataFrame { +function buildData(theme: GrafanaThemeV2, config: Record): 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: { diff --git a/packages/grafana-ui/src/components/Table/Table.test.tsx b/packages/grafana-ui/src/components/Table/Table.test.tsx index 69b5af5c6a1..e69cb013f13 100644 --- a/packages/grafana-ui/src/components/Table/Table.test.tsx +++ b/packages/grafana-ui/src/components/Table/Table.test.tsx @@ -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]; } diff --git a/packages/grafana-ui/src/components/Table/Table.tsx b/packages/grafana-ui/src/components/Table/Table.tsx index 2672ead0744..c5d804f8c63 100644 --- a/packages/grafana-ui/src/components/Table/Table.tsx +++ b/packages/grafana-ui/src/components/Table/Table.tsx @@ -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 = 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 diff --git a/packages/grafana-ui/src/components/Table/styles.ts b/packages/grafana-ui/src/components/Table/styles.ts index f775ae27e49..0898790de30 100644 --- a/packages/grafana-ui/src/components/Table/styles.ts +++ b/packages/grafana-ui/src/components/Table/styles.ts @@ -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; diff --git a/packages/grafana-ui/src/components/Timeline/TimelineChart.tsx b/packages/grafana-ui/src/components/Timeline/TimelineChart.tsx index ffd2eec9c18..3f8d480a621 100755 --- a/packages/grafana-ui/src/components/Timeline/TimelineChart.tsx +++ b/packages/grafana-ui/src/components/Timeline/TimelineChart.tsx @@ -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 } } -export const TimelineChart = withTheme(UnthemedTimelineChart); +export const TimelineChart = withTheme2(UnthemedTimelineChart); TimelineChart.displayName = 'TimelineChart'; diff --git a/packages/grafana-ui/src/components/Timeline/utils.ts b/packages/grafana-ui/src/components/Timeline/utils.ts index 2eb7d26a6e2..33ff91a77e3 100644 --- a/packages/grafana-ui/src/components/Timeline/utils.ts +++ b/packages/grafana-ui/src/components/Timeline/utils.ts @@ -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 diff --git a/packages/grafana-ui/src/components/uPlot/config/UPlotAxisBuilder.ts b/packages/grafana-ui/src/components/uPlot/config/UPlotAxisBuilder.ts index 6b499fb0060..8201be6a4e3 100644 --- a/packages/grafana-ui/src/components/uPlot/config/UPlotAxisBuilder.ts +++ b/packages/grafana-ui/src/components/uPlot/config/UPlotAxisBuilder.ts @@ -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 { 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, diff --git a/packages/grafana-ui/src/components/uPlot/config/UPlotConfigBuilder.test.ts b/packages/grafana-ui/src/components/uPlot/config/UPlotConfigBuilder.test.ts index 01a17fb41b0..2c7251c0036 100644 --- a/packages/grafana-ui/src/components/uPlot/config/UPlotConfigBuilder.test.ts +++ b/packages/grafana-ui/src/components/uPlot/config/UPlotConfigBuilder.test.ts @@ -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', () => { diff --git a/packages/grafana-ui/src/components/uPlot/config/UPlotSeriesBuilder.ts b/packages/grafana-ui/src/components/uPlot/config/UPlotSeriesBuilder.ts index 881c5d9bd1a..dad81e3dbe5 100755 --- a/packages/grafana-ui/src/components/uPlot/config/UPlotSeriesBuilder.ts +++ b/packages/grafana-ui/src/components/uPlot/config/UPlotSeriesBuilder.ts @@ -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 { diff --git a/packages/grafana-ui/src/components/uPlot/config/gradientFills.ts b/packages/grafana-ui/src/components/uPlot/config/gradientFills.ts index c96ef17ca3a..ea871c4bfb2 100644 --- a/packages/grafana-ui/src/components/uPlot/config/gradientFills.ts +++ b/packages/grafana-ui/src/components/uPlot/config/gradientFills.ts @@ -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(); diff --git a/packages/grafana-ui/src/components/uPlot/plugins/TooltipPlugin.tsx b/packages/grafana-ui/src/components/uPlot/plugins/TooltipPlugin.tsx index 5f4d14b326a..98404b0aaf6 100644 --- a/packages/grafana-ui/src/components/uPlot/plugins/TooltipPlugin.tsx +++ b/packages/grafana-ui/src/components/uPlot/plugins/TooltipPlugin.tsx @@ -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 = ({ config, ...otherProps }) => { + const theme = useTheme2(); const plotCtx = usePlotContext(); const plotCanvas = useRef(); const plotCanvasBBox = useRef({ left: 0, top: 0, right: 0, bottom: 0, width: 0, height: 0 }); @@ -81,7 +83,7 @@ export const TooltipPlugin: React.FC = ({ 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 = ({ 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 = ( diff --git a/packages/grafana-ui/src/utils/storybook/data.ts b/packages/grafana-ui/src/utils/storybook/data.ts index 0063fc482b7..ca4059d1adc 100644 --- a/packages/grafana-ui/src/utils/storybook/data.ts +++ b/packages/grafana-ui/src/utils/storybook/data.ts @@ -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: { diff --git a/public/app/core/logs_model.ts b/public/app/core/logs_model.ts index 62317195323..a383f1350f8 100644 --- a/public/app/core/logs_model.ts +++ b/public/app/core/logs_model.ts @@ -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({ diff --git a/public/app/features/alerting/state/actions.ts b/public/app/features/alerting/state/actions.ts index aa12cf15151..c3871f049f5 100644 --- a/public/app/features/alerting/state/actions.ts +++ b/public/app/features/alerting/state/actions.ts @@ -218,7 +218,7 @@ function handleJSONResponse(frames: DataFrameJSON[]) { overrides: [], }, replaceVariables: (value: any) => value, - theme: config.theme, + theme: config.theme2, }); } diff --git a/public/app/features/dashboard/state/PanelModel.ts b/public/app/features/dashboard/state/PanelModel.ts index 4c007eceb2d..1a29fc65641 100644 --- a/public/app/features/dashboard/state/PanelModel.ts +++ b/public/app/features/dashboard/state/PanelModel.ts @@ -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, }; } diff --git a/public/app/features/dashboard/utils/loadSnapshotData.ts b/public/app/features/dashboard/utils/loadSnapshotData.ts index d0ddf58f49d..8353915aefd 100644 --- a/public/app/features/dashboard/utils/loadSnapshotData.ts +++ b/public/app/features/dashboard/utils/loadSnapshotData.ts @@ -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, diff --git a/public/app/features/explore/ExploreGraphNGPanel.tsx b/public/app/features/explore/ExploreGraphNGPanel.tsx index b0becbba1f8..fd746d8777d 100644 --- a/public/app/features/explore/ExploreGraphNGPanel.tsx +++ b/public/app/features/explore/ExploreGraphNGPanel.tsx @@ -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({ diff --git a/public/app/features/explore/flotgraph/getGraphSeriesModel.ts b/public/app/features/explore/flotgraph/getGraphSeriesModel.ts index 0b47da7ce2d..1a72abc5754 100644 --- a/public/app/features/explore/flotgraph/getGraphSeriesModel.ts +++ b/public/app/features/explore/flotgraph/getGraphSeriesModel.ts @@ -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({ diff --git a/public/app/features/explore/utils/decorators.ts b/public/app/features/explore/utils/decorators.ts index a9bae4d5725..cce53862930 100644 --- a/public/app/features/explore/utils/decorators.ts +++ b/public/app/features/explore/utils/decorators.ts @@ -118,7 +118,7 @@ export const decorateWithTableResult = (data: ExplorePanelData): Observable { // 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; diff --git a/public/app/features/inspector/InspectStatsTable.tsx b/public/app/features/inspector/InspectStatsTable.tsx index bf58de5631f..ef482ecfd40 100644 --- a/public/app/features/inspector/InspectStatsTable.tsx +++ b/public/app/features/inspector/InspectStatsTable.tsx @@ -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 = ({ 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 = ({ timeZone, return ( {stat.displayName} - {formatStat(stat, timeZone)} + {formatStat(stat, timeZone, theme)} ); })} @@ -44,22 +43,22 @@ export const InspectStatsTable: React.FC = ({ 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; diff --git a/public/app/features/panel/PanelRenderer.tsx b/public/app/features/panel/PanelRenderer.tsx index 8fc187cc0bd..4d9430cb505 100644 --- a/public/app/features/panel/PanelRenderer.tsx +++ b/public/app/features/panel/PanelRenderer.tsx @@ -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

(props: PanelRendererProps) { 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]); }; diff --git a/public/app/features/panel/panellinks/linkSuppliers.test.ts b/public/app/features/panel/panellinks/linkSuppliers.test.ts index f33f47faa84..e5d0611fde7 100644 --- a/public/app/features/panel/panellinks/linkSuppliers.test.ts +++ b/public/app/features/panel/panellinks/linkSuppliers.test.ts @@ -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; diff --git a/public/app/features/panel/panellinks/linkSuppliers.ts b/public/app/features/panel/panellinks/linkSuppliers.ts index 8f91b821123..65f2d075b3d 100644 --- a/public/app/features/panel/panellinks/linkSuppliers.ts +++ b/public/app/features/panel/panellinks/linkSuppliers.ts @@ -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 { 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: () => [{}], diff --git a/public/app/features/sandbox/TestStuffPage.tsx b/public/app/features/sandbox/TestStuffPage.tsx index 5640ac3597d..fd195646e40 100644 --- a/public/app/features/sandbox/TestStuffPage.tsx +++ b/public/app/features/sandbox/TestStuffPage.tsx @@ -103,7 +103,7 @@ export function getDefaultState(): State { overrides: [], }, replaceVariables: (v: string) => v, - theme: config.theme, + theme: config.theme2, }; const dataConfig = { diff --git a/public/app/plugins/panel/bargauge/BarGaugePanel.tsx b/public/app/plugins/panel/bargauge/BarGaugePanel.tsx index 2c02b7dcbc9..2a0e2920869 100644 --- a/public/app/plugins/panel/bargauge/BarGaugePanel.tsx +++ b/public/app/plugins/panel/bargauge/BarGaugePanel.tsx @@ -40,7 +40,7 @@ export class BarGaugePanel extends PureComponent> { 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> { fieldConfig, reduceOptions: options.reduceOptions, replaceVariables, - theme: config.theme, + theme: config.theme2, data: data.series, timeZone, }); diff --git a/public/app/plugins/panel/gauge/GaugePanel.tsx b/public/app/plugins/panel/gauge/GaugePanel.tsx index fa2224bbd74..54a09983a3c 100644 --- a/public/app/plugins/panel/gauge/GaugePanel.tsx +++ b/public/app/plugins/panel/gauge/GaugePanel.tsx @@ -56,7 +56,7 @@ export class GaugePanel extends PureComponent> { fieldConfig, reduceOptions: options.reduceOptions, replaceVariables, - theme: config.theme, + theme: config.theme2, data: data.series, timeZone, }); diff --git a/public/app/plugins/panel/graph/graph.ts b/public/app/plugins/panel/graph/graph.ts index 1b14ed122c9..b4c5bb2f019 100644 --- a/public/app/plugins/panel/graph/graph.ts +++ b/public/app/plugins/panel/graph/graph.ts @@ -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 diff --git a/public/app/plugins/panel/live/LivePanel.tsx b/public/app/plugins/panel/live/LivePanel.tsx index b81097e0387..578a30c6cee 100755 --- a/public/app/plugins/panel/live/LivePanel.tsx +++ b/public/app/plugins/panel/live/LivePanel.tsx @@ -188,7 +188,7 @@ export class LivePanel extends PureComponent { const data: PanelData = { series: applyFieldOverrides({ data: [message], - theme: config.theme, + theme: config.theme2, replaceVariables: (v: string) => v, fieldConfig: { defaults: {}, diff --git a/public/app/plugins/panel/stat/StatPanel.tsx b/public/app/plugins/panel/stat/StatPanel.tsx index d886d4f660d..771a054397a 100644 --- a/public/app/plugins/panel/stat/StatPanel.tsx +++ b/public/app/plugins/panel/stat/StatPanel.tsx @@ -45,7 +45,7 @@ export class StatPanel extends PureComponent> { 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> { fieldConfig, reduceOptions: options.reduceOptions, replaceVariables, - theme: config.theme, + theme: config.theme2, data: data.series, sparkline: options.graphMode !== BigValueGraphMode.None, timeZone, diff --git a/public/app/plugins/panel/timeseries/plugins/ContextMenuPlugin.tsx b/public/app/plugins/panel/timeseries/plugins/ContextMenuPlugin.tsx index 4d88c274ac7..03cc4784786 100644 --- a/public/app/plugins/panel/timeseries/plugins/ContextMenuPlugin.tsx +++ b/public/app/plugins/panel/timeseries/plugins/ContextMenuPlugin.tsx @@ -14,7 +14,6 @@ import { CartesianCoords2D, DataFrame, DataFrameView, - getDisplayProcessor, getFieldDisplayName, InterpolateFunction, TimeZone, @@ -198,7 +197,7 @@ export const ContextMenuView: React.FC = ({ 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];