mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
ColorSchemes: Adds more color schemes and text colors that depend on the background (#28305)
* Adding more color modes and text colors that depend on the background color * Updates * Updated * Another big value fix * Fixing unit tests * Updated * Updated test * Update * Updated * Updated * Updated * Updated * Added new demo dashboard * Updated * updated * Updated * Updateed * added beta notice * Fixed e2e test
This commit is contained in:
parent
95a1993443
commit
566cd2c6af
338
devenv/dev-dashboards/panel-common/color_modes.json
Normal file
338
devenv/dev-dashboards/panel-common/color_modes.json
Normal file
@ -0,0 +1,338 @@
|
||||
{
|
||||
"annotations": {
|
||||
"list": [
|
||||
{
|
||||
"builtIn": 1,
|
||||
"datasource": "-- Grafana --",
|
||||
"enable": true,
|
||||
"hide": true,
|
||||
"iconColor": "rgba(0, 211, 255, 1)",
|
||||
"name": "Annotations & Alerts",
|
||||
"type": "dashboard"
|
||||
}
|
||||
]
|
||||
},
|
||||
"editable": true,
|
||||
"gnetId": null,
|
||||
"graphTooltip": 0,
|
||||
"links": [],
|
||||
"panels": [
|
||||
{
|
||||
"datasource": "gdev-testdata",
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": {
|
||||
"mode": "continuous-BlYlRd"
|
||||
},
|
||||
"custom": {
|
||||
"align": "center",
|
||||
"displayMode": "color-background",
|
||||
"filterable": false
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "percentage",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
},
|
||||
{
|
||||
"color": "blue",
|
||||
"value": 20
|
||||
},
|
||||
{
|
||||
"color": "orange",
|
||||
"value": 60
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
"value": 70
|
||||
}
|
||||
]
|
||||
},
|
||||
"unit": "degree"
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byName",
|
||||
"options": "Field"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "custom.displayMode"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 16,
|
||||
"w": 19,
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"id": 4,
|
||||
"options": {
|
||||
"showHeader": true,
|
||||
"sortBy": [
|
||||
{
|
||||
"desc": true,
|
||||
"displayName": "Last"
|
||||
}
|
||||
]
|
||||
},
|
||||
"pluginVersion": "7.4.0-pre",
|
||||
"targets": [
|
||||
{
|
||||
"alias": "",
|
||||
"csvWave": {
|
||||
"timeStep": 60,
|
||||
"valuesCSV": "0,0,2,2,1,1"
|
||||
},
|
||||
"lines": 10,
|
||||
"points": [],
|
||||
"pulseWave": {
|
||||
"offCount": 3,
|
||||
"offValue": 1,
|
||||
"onCount": 3,
|
||||
"onValue": 2,
|
||||
"timeStep": 60
|
||||
},
|
||||
"refId": "A",
|
||||
"scenarioId": "random_walk",
|
||||
"seriesCount": 15,
|
||||
"stream": {
|
||||
"bands": 1,
|
||||
"noise": 2.2,
|
||||
"speed": 250,
|
||||
"spread": 3.5,
|
||||
"type": "signal"
|
||||
},
|
||||
"stringInput": ""
|
||||
}
|
||||
],
|
||||
"timeFrom": null,
|
||||
"timeShift": null,
|
||||
"title": "Gradient color schemes",
|
||||
"transformations": [
|
||||
{
|
||||
"id": "reduce",
|
||||
"options": {
|
||||
"reducers": ["max", "mean", "last", "min"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "organize",
|
||||
"options": {
|
||||
"excludeByName": {
|
||||
"Field": false
|
||||
},
|
||||
"indexByName": {},
|
||||
"renameByName": {}
|
||||
}
|
||||
}
|
||||
],
|
||||
"type": "table"
|
||||
},
|
||||
{
|
||||
"datasource": null,
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": {
|
||||
"mode": "continuous-blues"
|
||||
},
|
||||
"custom": {},
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
"value": 20
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 26,
|
||||
"w": 5,
|
||||
"x": 19,
|
||||
"y": 0
|
||||
},
|
||||
"id": 2,
|
||||
"options": {
|
||||
"colorMode": "background",
|
||||
"graphMode": "none",
|
||||
"justifyMode": "auto",
|
||||
"orientation": "auto",
|
||||
"reduceOptions": {
|
||||
"calcs": ["mean"],
|
||||
"fields": "",
|
||||
"values": false
|
||||
},
|
||||
"textMode": "value"
|
||||
},
|
||||
"pluginVersion": "7.4.0-pre",
|
||||
"targets": [
|
||||
{
|
||||
"alias": "",
|
||||
"csvWave": {
|
||||
"timeStep": 60,
|
||||
"valuesCSV": "0,0,2,2,1,1"
|
||||
},
|
||||
"labels": "",
|
||||
"lines": 10,
|
||||
"points": [],
|
||||
"pulseWave": {
|
||||
"offCount": 3,
|
||||
"offValue": 1,
|
||||
"onCount": 3,
|
||||
"onValue": 2,
|
||||
"timeStep": 60
|
||||
},
|
||||
"refId": "A",
|
||||
"scenarioId": "random_walk",
|
||||
"seriesCount": 30,
|
||||
"stream": {
|
||||
"bands": 1,
|
||||
"noise": 2.2,
|
||||
"speed": 250,
|
||||
"spread": 3.5,
|
||||
"type": "signal"
|
||||
},
|
||||
"stringInput": ""
|
||||
}
|
||||
],
|
||||
"timeFrom": null,
|
||||
"timeShift": null,
|
||||
"title": "Stats",
|
||||
"type": "stat"
|
||||
},
|
||||
{
|
||||
"datasource": "gdev-testdata",
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": {
|
||||
"mode": "continuous-GrYlRd"
|
||||
},
|
||||
"custom": {
|
||||
"align": "center",
|
||||
"displayMode": "color-background",
|
||||
"filterable": false
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "percentage",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null
|
||||
},
|
||||
{
|
||||
"color": "blue",
|
||||
"value": 20
|
||||
},
|
||||
{
|
||||
"color": "orange",
|
||||
"value": 60
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
"value": 70
|
||||
}
|
||||
]
|
||||
},
|
||||
"unit": "degree"
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byName",
|
||||
"options": "Field"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "custom.displayMode"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 10,
|
||||
"w": 19,
|
||||
"x": 0,
|
||||
"y": 16
|
||||
},
|
||||
"id": 5,
|
||||
"options": {
|
||||
"displayMode": "lcd",
|
||||
"orientation": "auto",
|
||||
"reduceOptions": {
|
||||
"calcs": ["mean"],
|
||||
"fields": "",
|
||||
"values": false
|
||||
},
|
||||
"showUnfilled": true
|
||||
},
|
||||
"pluginVersion": "7.4.0-pre",
|
||||
"targets": [
|
||||
{
|
||||
"alias": "",
|
||||
"csvWave": {
|
||||
"timeStep": 60,
|
||||
"valuesCSV": "0,0,2,2,1,1"
|
||||
},
|
||||
"lines": 10,
|
||||
"points": [],
|
||||
"pulseWave": {
|
||||
"offCount": 3,
|
||||
"offValue": 1,
|
||||
"onCount": 3,
|
||||
"onValue": 2,
|
||||
"timeStep": 60
|
||||
},
|
||||
"refId": "A",
|
||||
"scenarioId": "random_walk",
|
||||
"seriesCount": 15,
|
||||
"stream": {
|
||||
"bands": 1,
|
||||
"noise": 2.2,
|
||||
"speed": 250,
|
||||
"spread": 3.5,
|
||||
"type": "signal"
|
||||
},
|
||||
"stringInput": ""
|
||||
}
|
||||
],
|
||||
"timeFrom": null,
|
||||
"timeShift": null,
|
||||
"title": "Bar Gauge LCD",
|
||||
"transformations": [],
|
||||
"type": "bargauge"
|
||||
}
|
||||
],
|
||||
"schemaVersion": 26,
|
||||
"style": "dark",
|
||||
"tags": ["gdev", "demo"],
|
||||
"templating": {
|
||||
"list": []
|
||||
},
|
||||
"time": {
|
||||
"from": "now-6h",
|
||||
"to": "now"
|
||||
},
|
||||
"timepicker": {},
|
||||
"timezone": "",
|
||||
"title": "Gradient Color modes",
|
||||
"uid": "inxsweKGz",
|
||||
"version": 17
|
||||
}
|
@ -29,7 +29,7 @@ e2e.scenario({
|
||||
e2e.components.DashboardLinks.link()
|
||||
.should('be.visible')
|
||||
.and(links => {
|
||||
expect(links).to.have.length(13);
|
||||
expect(links).to.have.length.greaterThan(13);
|
||||
|
||||
for (let index = 0; index < links.length; index++) {
|
||||
expect(Cypress.$(links[index]).attr('href')).contains(`var-custom=${variableValue}`);
|
||||
|
@ -3,13 +3,14 @@ import _ from 'lodash';
|
||||
|
||||
// Types
|
||||
import { Field, FieldType } from '../types/dataFrame';
|
||||
import { GrafanaTheme, GrafanaThemeType } from '../types/theme';
|
||||
import { GrafanaTheme } from '../types/theme';
|
||||
import { DecimalCount, DecimalInfo, 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';
|
||||
|
||||
interface DisplayProcessorOptions {
|
||||
field: Partial<Field>;
|
||||
@ -41,7 +42,7 @@ export function getDisplayProcessor(options?: DisplayProcessorOptions): DisplayP
|
||||
const config = field.config ?? {};
|
||||
|
||||
// Theme should be required or we need access to default theme instance from here
|
||||
const theme = options.theme ?? ({ type: GrafanaThemeType.Dark } as GrafanaTheme);
|
||||
const theme = options.theme ?? getTestTheme();
|
||||
|
||||
let unit = config.unit;
|
||||
let hasDateUnit = unit && (timeFormats[unit] || unit.startsWith('time:'));
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { Field, GrafanaThemeType, GrafanaTheme, FieldColorModeId } from '../types';
|
||||
import { Field, FieldColorModeId } from '../types';
|
||||
import { getTestTheme } from '../utils/testdata/testTheme';
|
||||
import { fieldColorModeRegistry, FieldValueColorCalculator } from './fieldColor';
|
||||
|
||||
describe('fieldColorModeRegistry', () => {
|
||||
@ -9,10 +10,7 @@ describe('fieldColorModeRegistry', () => {
|
||||
|
||||
function getCalculator(options: GetCalcOptions): FieldValueColorCalculator {
|
||||
const mode = fieldColorModeRegistry.get(options.mode);
|
||||
return mode.getCalculator(
|
||||
{ state: { seriesIndex: options.seriesIndex } } as Field,
|
||||
{ type: GrafanaThemeType.Dark } as GrafanaTheme
|
||||
);
|
||||
return mode.getCalculator({ state: { seriesIndex: options.seriesIndex } } as Field, getTestTheme());
|
||||
}
|
||||
|
||||
it('Schemes should interpolate', () => {
|
||||
|
@ -54,20 +54,81 @@ export const fieldColorModeRegistry = new Registry<FieldColorMode>(() => {
|
||||
// }),
|
||||
new FieldColorSchemeMode({
|
||||
id: FieldColorModeId.PaletteClassic,
|
||||
name: 'By series / Classic palette',
|
||||
//description: 'Assigns color based on series or field index',
|
||||
name: 'Classic palette',
|
||||
isContinuous: false,
|
||||
isByValue: false,
|
||||
colors: classicColors,
|
||||
}),
|
||||
new FieldColorSchemeMode({
|
||||
id: 'continuous-GrYlRd',
|
||||
name: 'By value / Green Yellow Red (gradient)',
|
||||
//description: 'Interpolated colors based value, min and max',
|
||||
name: 'Green-Yellow-Red',
|
||||
isContinuous: true,
|
||||
isByValue: true,
|
||||
colors: ['green', 'yellow', 'red'],
|
||||
}),
|
||||
new FieldColorSchemeMode({
|
||||
id: 'continuous-BlYlRd',
|
||||
name: 'Blue-Yellow-Red',
|
||||
isContinuous: true,
|
||||
isByValue: true,
|
||||
colors: ['dark-blue', 'super-light-yellow', 'dark-red'],
|
||||
}),
|
||||
new FieldColorSchemeMode({
|
||||
id: 'continuous-RdYlBl',
|
||||
name: 'Red-Yellow-Blue',
|
||||
isContinuous: true,
|
||||
isByValue: true,
|
||||
colors: ['dark-red', 'super-light-yellow', 'dark-blue'],
|
||||
}),
|
||||
new FieldColorSchemeMode({
|
||||
id: 'continuous-YlRd',
|
||||
name: 'Yellow-Red',
|
||||
isContinuous: true,
|
||||
isByValue: true,
|
||||
colors: ['super-light-yellow', 'dark-red'],
|
||||
}),
|
||||
new FieldColorSchemeMode({
|
||||
id: 'continuous-BlPu',
|
||||
name: 'Blue-Purple',
|
||||
isContinuous: true,
|
||||
isByValue: true,
|
||||
colors: ['blue', 'purple'],
|
||||
}),
|
||||
new FieldColorSchemeMode({
|
||||
id: 'continuous-YlBl',
|
||||
name: 'Yellow-Blue',
|
||||
isContinuous: true,
|
||||
isByValue: true,
|
||||
colors: ['super-light-yellow', 'dark-blue'],
|
||||
}),
|
||||
new FieldColorSchemeMode({
|
||||
id: 'continuous-blues',
|
||||
name: 'Blues',
|
||||
isContinuous: true,
|
||||
isByValue: true,
|
||||
colors: ['panel-bg', 'dark-blue'],
|
||||
}),
|
||||
new FieldColorSchemeMode({
|
||||
id: 'continuous-reds',
|
||||
name: 'Reds',
|
||||
isContinuous: true,
|
||||
isByValue: true,
|
||||
colors: ['panel-bg', 'dark-red'],
|
||||
}),
|
||||
new FieldColorSchemeMode({
|
||||
id: 'continuous-greens',
|
||||
name: 'Greens',
|
||||
isContinuous: true,
|
||||
isByValue: true,
|
||||
colors: ['panel-bg', 'dark-green'],
|
||||
}),
|
||||
new FieldColorSchemeMode({
|
||||
id: 'continuous-purples',
|
||||
name: 'Purples',
|
||||
isContinuous: true,
|
||||
isByValue: true,
|
||||
colors: ['panel-bg', 'dark-purple'],
|
||||
}),
|
||||
];
|
||||
});
|
||||
|
||||
|
@ -2,9 +2,9 @@ import merge from 'lodash/merge';
|
||||
import { getFieldDisplayValues, GetFieldDisplayValuesOptions } from './fieldDisplay';
|
||||
import { toDataFrame } from '../dataframe/processDataFrame';
|
||||
import { ReducerID } from '../transformations/fieldReducer';
|
||||
import { GrafanaTheme } from '../types/theme';
|
||||
import { MappingType } from '../types';
|
||||
import { standardFieldConfigEditorRegistry } from './standardFieldConfigEditorRegistry';
|
||||
import { getTestTheme } from '../utils/testdata/testTheme';
|
||||
|
||||
describe('FieldDisplay', () => {
|
||||
beforeAll(() => {
|
||||
@ -241,7 +241,7 @@ function createDisplayOptions(extend: Partial<GetFieldDisplayValuesOptions> = {}
|
||||
overrides: [],
|
||||
defaults: {},
|
||||
},
|
||||
theme: {} as GrafanaTheme,
|
||||
theme: getTestTheme(),
|
||||
};
|
||||
|
||||
return merge<GetFieldDisplayValuesOptions, any>(options, extend);
|
||||
|
@ -15,7 +15,6 @@ import {
|
||||
FieldConfigPropertyItem,
|
||||
FieldConfigSource,
|
||||
FieldType,
|
||||
GrafanaTheme,
|
||||
InterpolateFunction,
|
||||
ThresholdsMode,
|
||||
FieldColorModeId,
|
||||
@ -28,6 +27,7 @@ import { FieldConfigOptionsRegistry } from './FieldConfigOptionsRegistry';
|
||||
import { getFieldDisplayName } from './fieldState';
|
||||
import { ArrayVector } from '../vector';
|
||||
import { getDisplayProcessor } from './displayProcessor';
|
||||
import { getTestTheme } from '../utils/testdata/testTheme';
|
||||
|
||||
const property1: any = {
|
||||
id: 'custom.property1', // Match field properties
|
||||
@ -136,7 +136,7 @@ describe('applyFieldOverrides', () => {
|
||||
},
|
||||
replaceVariables: (value: any) => value,
|
||||
getDataSourceSettingsByUid: undefined as any,
|
||||
theme: {} as GrafanaTheme,
|
||||
theme: getTestTheme(),
|
||||
fieldConfigRegistry: new FieldConfigOptionsRegistry(),
|
||||
});
|
||||
|
||||
@ -199,7 +199,7 @@ describe('applyFieldOverrides', () => {
|
||||
fieldConfigRegistry: customFieldRegistry,
|
||||
getDataSourceSettingsByUid: undefined as any,
|
||||
replaceVariables: v => v,
|
||||
theme: {} as GrafanaTheme,
|
||||
theme: getTestTheme(),
|
||||
})[0];
|
||||
|
||||
const outField = processed.fields[0];
|
||||
@ -216,7 +216,7 @@ describe('applyFieldOverrides', () => {
|
||||
fieldConfig: src as FieldConfigSource, // defaults + overrides
|
||||
replaceVariables: (undefined as any) as InterpolateFunction,
|
||||
getDataSourceSettingsByUid: undefined as any,
|
||||
theme: (undefined as any) as GrafanaTheme,
|
||||
theme: getTestTheme(),
|
||||
fieldConfigRegistry: customFieldRegistry,
|
||||
})[0];
|
||||
const valueColumn = data.fields[1];
|
||||
@ -244,7 +244,7 @@ describe('applyFieldOverrides', () => {
|
||||
fieldConfig: src as FieldConfigSource, // defaults + overrides
|
||||
replaceVariables: (undefined as any) as InterpolateFunction,
|
||||
getDataSourceSettingsByUid: undefined as any,
|
||||
theme: (undefined as any) as GrafanaTheme,
|
||||
theme: getTestTheme(),
|
||||
autoMinMax: true,
|
||||
})[0];
|
||||
const valueColumn = data.fields[1];
|
||||
@ -268,7 +268,7 @@ describe('applyFieldOverrides', () => {
|
||||
return value;
|
||||
}) as InterpolateFunction,
|
||||
getDataSourceSettingsByUid: undefined as any,
|
||||
theme: (undefined as any) as GrafanaTheme,
|
||||
theme: getTestTheme(),
|
||||
autoMinMax: true,
|
||||
fieldConfigRegistry: customFieldRegistry,
|
||||
})[0];
|
||||
@ -521,7 +521,7 @@ describe('getLinksSupplier', () => {
|
||||
// this is used only for internal links so isn't needed here
|
||||
() => ({} as any),
|
||||
{
|
||||
theme: {} as GrafanaTheme,
|
||||
theme: getTestTheme(),
|
||||
}
|
||||
);
|
||||
supplier({});
|
||||
@ -568,7 +568,7 @@ describe('getLinksSupplier', () => {
|
||||
// We do not need to interpolate anything for this test
|
||||
(value, vars, format) => value,
|
||||
uid => ({ name: 'testDS' } as any),
|
||||
{ theme: {} as GrafanaTheme }
|
||||
{ theme: getTestTheme() }
|
||||
);
|
||||
const links = supplier({ valueRowIndex: 0 });
|
||||
expect(links.length).toBe(1);
|
||||
|
@ -2,6 +2,7 @@ import { getFieldDisplayValuesProxy } from './getFieldDisplayValuesProxy';
|
||||
import { applyFieldOverrides } from './fieldOverrides';
|
||||
import { toDataFrame } from '../dataframe';
|
||||
import { GrafanaTheme } from '../types';
|
||||
import { getTestTheme } from '../utils/testdata/testTheme';
|
||||
|
||||
describe('getFieldDisplayValuesProxy', () => {
|
||||
const data = applyFieldOverrides({
|
||||
@ -30,7 +31,7 @@ describe('getFieldDisplayValuesProxy', () => {
|
||||
replaceVariables: (val: string) => val,
|
||||
getDataSourceSettingsByUid: (val: string) => ({} as any),
|
||||
timeZone: 'utc',
|
||||
theme: {} as GrafanaTheme,
|
||||
theme: getTestTheme(),
|
||||
autoMinMax: true,
|
||||
})[0];
|
||||
|
||||
|
@ -1,7 +1,8 @@
|
||||
import { ThresholdsMode, Field, FieldType, GrafanaThemeType, GrafanaTheme } from '../types';
|
||||
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';
|
||||
|
||||
describe('getScaleCalculator', () => {
|
||||
it('should return percent, threshold and color', () => {
|
||||
@ -18,7 +19,7 @@ describe('getScaleCalculator', () => {
|
||||
values: new ArrayVector([0, 50, 100]),
|
||||
};
|
||||
|
||||
const calc = getScaleCalculator(field, { type: GrafanaThemeType.Dark } as GrafanaTheme);
|
||||
const calc = getScaleCalculator(field, getTestTheme());
|
||||
expect(calc(70)).toEqual({
|
||||
percent: 0.7,
|
||||
threshold: thresholds[1],
|
||||
|
@ -34,7 +34,8 @@ export type Color =
|
||||
| 'dark-purple'
|
||||
| 'semi-dark-purple'
|
||||
| 'light-purple'
|
||||
| 'super-light-purple';
|
||||
| 'super-light-purple'
|
||||
| 'panel-bg';
|
||||
|
||||
type ThemeVariants = {
|
||||
dark: string;
|
||||
@ -82,6 +83,8 @@ export function buildColorsMapForTheme(theme: GrafanaTheme): Record<Color, strin
|
||||
}
|
||||
}
|
||||
|
||||
colorsMap['panel-bg'] = theme.colors.panelBg;
|
||||
|
||||
return colorsMap;
|
||||
}
|
||||
|
||||
@ -118,7 +121,25 @@ export function getColorForTheme(color: string, theme: GrafanaTheme): string {
|
||||
export function getColorFromHexRgbOrName(color: string, type?: GrafanaThemeType): string {
|
||||
const themeType = type ?? GrafanaThemeType.Dark;
|
||||
|
||||
return getColorForTheme(color, ({ type: themeType } as unknown) as GrafanaTheme);
|
||||
if (themeType === GrafanaThemeType.Dark) {
|
||||
const darkTheme = ({
|
||||
type: themeType,
|
||||
colors: {
|
||||
panelBg: '#141619',
|
||||
},
|
||||
} as unknown) as GrafanaTheme;
|
||||
|
||||
return getColorForTheme(color, darkTheme);
|
||||
}
|
||||
|
||||
const lightTheme = ({
|
||||
type: themeType,
|
||||
colors: {
|
||||
panelBg: '#000000',
|
||||
},
|
||||
} as unknown) as GrafanaTheme;
|
||||
|
||||
return getColorForTheme(color, lightTheme);
|
||||
}
|
||||
|
||||
const buildNamedColorsPalette = () => {
|
||||
|
12
packages/grafana-data/src/utils/testdata/testTheme.ts
vendored
Normal file
12
packages/grafana-data/src/utils/testdata/testTheme.ts
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
import { GrafanaTheme, GrafanaThemeType } from '../../types/theme';
|
||||
|
||||
export function getTestTheme(type: GrafanaThemeType = GrafanaThemeType.Dark): GrafanaTheme {
|
||||
return ({
|
||||
type,
|
||||
isDark: type === GrafanaThemeType.Dark,
|
||||
isLight: type === GrafanaThemeType.Light,
|
||||
colors: {
|
||||
panelBg: 'white',
|
||||
},
|
||||
} as unknown) as GrafanaTheme;
|
||||
}
|
@ -9,6 +9,7 @@ import { calculateFontSize } from '../../utils/measureText';
|
||||
|
||||
// Types
|
||||
import { BigValueColorMode, Props, BigValueJustifyMode, BigValueTextMode } from './BigValue';
|
||||
import { getTextColorForBackground } from '../../utils';
|
||||
|
||||
const LINE_HEIGHT = 1.2;
|
||||
const MAX_TITLE_SIZE = 30;
|
||||
@ -51,7 +52,7 @@ export abstract class BigValueLayout {
|
||||
};
|
||||
|
||||
if (this.props.colorMode === BigValueColorMode.Background) {
|
||||
styles.color = 'white';
|
||||
styles.color = getTextColorForBackground(this.valueColor);
|
||||
}
|
||||
|
||||
return styles;
|
||||
@ -69,7 +70,7 @@ export abstract class BigValueLayout {
|
||||
styles.color = this.valueColor;
|
||||
break;
|
||||
case BigValueColorMode.Background:
|
||||
styles.color = 'white';
|
||||
styles.color = getTextColorForBackground(this.valueColor);
|
||||
}
|
||||
|
||||
return styles;
|
||||
|
@ -30,7 +30,7 @@ exports[`BigValue Render with basic options should render 1`] = `
|
||||
<FormattedDisplayValue
|
||||
style={
|
||||
Object {
|
||||
"color": "white",
|
||||
"color": "#202226",
|
||||
"fontSize": 230,
|
||||
"fontWeight": 500,
|
||||
"lineHeight": 1.2,
|
||||
|
@ -23,9 +23,11 @@ export const FieldColorEditor: React.FC<FieldConfigEditorProps<FieldColor | unde
|
||||
const styles = useStyles(getStyles);
|
||||
|
||||
const options = fieldColorModeRegistry.list().map(mode => {
|
||||
let suffix = mode.isByValue ? ' (by value)' : '';
|
||||
|
||||
return {
|
||||
value: mode.id,
|
||||
label: mode.name,
|
||||
label: `${mode.name}${suffix}`,
|
||||
description: mode.description,
|
||||
isContinuous: mode.isContinuous,
|
||||
isByValue: mode.isByValue,
|
||||
|
@ -5,6 +5,7 @@ import { TableCellDisplayMode, TableCellProps } from './types';
|
||||
import tinycolor from 'tinycolor2';
|
||||
import { TableStyles } from './styles';
|
||||
import { FilterActions } from './FilterActions';
|
||||
import { getTextColorForBackground } from '../../utils';
|
||||
|
||||
export const DefaultCell: FC<TableCellProps> = props => {
|
||||
const { field, cell, tableStyles, row, cellProps } = props;
|
||||
@ -65,7 +66,12 @@ function getCellStyle(tableStyles: TableStyles, field: Field, displayValue: Disp
|
||||
.spin(5)
|
||||
.toRgbString();
|
||||
|
||||
return tableStyles.buildCellContainerStyle('white', `linear-gradient(120deg, ${bgColor2}, ${displayValue.color})`);
|
||||
const textColor = getTextColorForBackground(displayValue.color!);
|
||||
|
||||
return tableStyles.buildCellContainerStyle(
|
||||
textColor,
|
||||
`linear-gradient(120deg, ${bgColor2}, ${displayValue.color})`
|
||||
);
|
||||
}
|
||||
|
||||
return tableStyles.cellContainer;
|
||||
|
@ -4,6 +4,8 @@ import flattenDeep from 'lodash/flattenDeep';
|
||||
import chunk from 'lodash/chunk';
|
||||
import zip from 'lodash/zip';
|
||||
import tinycolor from 'tinycolor2';
|
||||
import lightTheme from '../themes/light';
|
||||
import darkTheme from '../themes/dark';
|
||||
|
||||
export const PALETTE_ROWS = 4;
|
||||
export const PALETTE_COLUMNS = 14;
|
||||
@ -93,4 +95,9 @@ function hslToHex(color: any) {
|
||||
return tinycolor(color).toHexString();
|
||||
}
|
||||
|
||||
export function getTextColorForBackground(color: string) {
|
||||
const b = tinycolor(color).getBrightness();
|
||||
return b > 150 ? lightTheme.colors.textStrong : darkTheme.colors.textStrong;
|
||||
}
|
||||
|
||||
export let sortedColors = sortColorsByHue(colors);
|
||||
|
@ -1,6 +1,9 @@
|
||||
let canvas: HTMLCanvasElement | null = null;
|
||||
const cache: Record<string, TextMetrics> = {};
|
||||
|
||||
/**
|
||||
* @beta
|
||||
*/
|
||||
export function measureText(text: string, fontSize: number): TextMetrics {
|
||||
const fontStyle = `${fontSize}px 'Roboto'`;
|
||||
const cacheKey = text + fontStyle;
|
||||
@ -26,6 +29,9 @@ export function measureText(text: string, fontSize: number): TextMetrics {
|
||||
return metrics;
|
||||
}
|
||||
|
||||
/**
|
||||
* @beta
|
||||
*/
|
||||
export function calculateFontSize(text: string, width: number, height: number, lineHeight: number, maxSize?: number) {
|
||||
// calculate width in 14px
|
||||
const textSize = measureText(text, 14);
|
||||
|
@ -1,8 +1,9 @@
|
||||
import { getFieldLinksSupplier } from './linkSuppliers';
|
||||
import { applyFieldOverrides, DataFrameView, dateTime, FieldDisplay, GrafanaTheme, toDataFrame } from '@grafana/data';
|
||||
import { applyFieldOverrides, 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;
|
||||
@ -91,7 +92,7 @@ describe('getFieldLinksSupplier', () => {
|
||||
replaceVariables: (val: string) => val,
|
||||
getDataSourceSettingsByUid: (val: string) => ({} as any),
|
||||
timeZone: 'utc',
|
||||
theme: {} as GrafanaTheme,
|
||||
theme: getTheme(),
|
||||
autoMinMax: true,
|
||||
})[0];
|
||||
|
||||
|
@ -3,7 +3,7 @@ import TableModel from 'app/core/table_model';
|
||||
import { TableRenderer } from '../renderer';
|
||||
import { ScopedVars, TimeZone } from '@grafana/data';
|
||||
import { ColumnRender } from '../types';
|
||||
import { config } from 'app/core/config';
|
||||
import { getTheme } from '@grafana/ui';
|
||||
|
||||
const utc: TimeZone = 'utc';
|
||||
|
||||
@ -211,7 +211,7 @@ describe('when rendering table', () => {
|
||||
};
|
||||
|
||||
//@ts-ignore
|
||||
const renderer = new TableRenderer(panel, table, utc, sanitize, templateSrv, config.theme);
|
||||
const renderer = new TableRenderer(panel, table, utc, sanitize, templateSrv, getTheme());
|
||||
|
||||
it('time column should be formatted', () => {
|
||||
const html = renderer.renderCell(0, 0, 1388556366666);
|
||||
@ -467,7 +467,7 @@ describe('when rendering table with different patterns', () => {
|
||||
};
|
||||
|
||||
//@ts-ignore
|
||||
const renderer = new TableRenderer(panel, table, utc, sanitize, templateSrv);
|
||||
const renderer = new TableRenderer(panel, table, utc, sanitize, templateSrv, getTheme());
|
||||
const html = renderer.renderCell(1, 0, 1230);
|
||||
|
||||
expect(html).toBe(expected);
|
||||
@ -537,7 +537,7 @@ describe('when rendering cells with different alignment options', () => {
|
||||
};
|
||||
|
||||
//@ts-ignore
|
||||
const renderer = new TableRenderer(panel, table, utc, sanitize, templateSrv);
|
||||
const renderer = new TableRenderer(panel, table, utc, sanitize, templateSrv, getTheme());
|
||||
const html = renderer.renderCell(1, 0, 42);
|
||||
|
||||
expect(html).toBe(expected);
|
||||
|
Loading…
Reference in New Issue
Block a user