mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[Gauge] Custom color support (#126882)
* Fixed case if uiState is undefined. * Fixed wrong behavior of the coloring in the percentage mode * Update src/plugins/chart_expressions/expression_gauge/public/components/gauge_component.tsx Co-authored-by: Stratoula Kalafateli <stratoula1@gmail.com> * Update src/plugins/chart_expressions/expression_gauge/public/components/gauge_component.tsx Co-authored-by: Stratoula Kalafateli <stratoula1@gmail.com> * Fixed bug, related to the formatting behavior while picking overrided color. Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Stratoula Kalafateli <stratoula1@gmail.com>
This commit is contained in:
parent
f5556f1327
commit
2836018b0e
4 changed files with 70 additions and 7 deletions
|
@ -6,6 +6,7 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { PersistedState } from '../../../../visualizations/public';
|
||||
import type { ChartsPluginSetup, PaletteRegistry } from '../../../../charts/public';
|
||||
import type { IFieldFormat, SerializedFieldFormat } from '../../../../field_formats/common';
|
||||
import type { GaugeExpressionProps } from './expression_functions';
|
||||
|
@ -16,6 +17,7 @@ export type GaugeRenderProps = GaugeExpressionProps & {
|
|||
formatFactory: FormatFactory;
|
||||
chartsThemeService: ChartsPluginSetup['theme'];
|
||||
paletteService: PaletteRegistry;
|
||||
uiState: PersistedState;
|
||||
};
|
||||
|
||||
export interface ColorStop {
|
||||
|
|
|
@ -79,6 +79,16 @@ const createData = (
|
|||
};
|
||||
};
|
||||
|
||||
const mockState = new Map();
|
||||
const uiState = {
|
||||
get: jest
|
||||
.fn()
|
||||
.mockImplementation((key, fallback) => (mockState.has(key) ? mockState.get(key) : fallback)),
|
||||
set: jest.fn().mockImplementation((key, value) => mockState.set(key, value)),
|
||||
emit: jest.fn(),
|
||||
setSilent: jest.fn(),
|
||||
} as any;
|
||||
|
||||
describe('GaugeComponent', function () {
|
||||
let wrapperProps: GaugeRenderProps;
|
||||
|
||||
|
@ -89,6 +99,7 @@ describe('GaugeComponent', function () {
|
|||
args,
|
||||
formatFactory: formatService.deserialize,
|
||||
paletteService: await paletteThemeService.getPalettes(),
|
||||
uiState,
|
||||
};
|
||||
});
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
import React, { FC, memo, useCallback } from 'react';
|
||||
import { Chart, Goal, Settings } from '@elastic/charts';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import { FieldFormat } from '../../../../field_formats/common';
|
||||
import type { CustomPaletteState, PaletteOutput } from '../../../../charts/public';
|
||||
import { EmptyPlaceholder } from '../../../../charts/public';
|
||||
import { isVisDimension } from '../../../../visualizations/common/utils';
|
||||
|
@ -183,8 +184,23 @@ const calculateRealRangeValueMax = (
|
|||
return max;
|
||||
};
|
||||
|
||||
const getPreviousSectionValue = (value: number, bands: number[]) => {
|
||||
// bands value is equal to the stop. The purpose of this value is coloring the previous section, which is smaller, then the band.
|
||||
// So, the smaller value should be taken. For the first element -1, for the next - middle value of the previous section.
|
||||
|
||||
let prevSectionValue = value - 1;
|
||||
const valueIndex = bands.indexOf(value);
|
||||
const prevBand = bands[valueIndex - 1];
|
||||
const curBand = bands[valueIndex];
|
||||
if (valueIndex > 0) {
|
||||
prevSectionValue = value - (curBand - prevBand) / 2;
|
||||
}
|
||||
|
||||
return prevSectionValue;
|
||||
};
|
||||
|
||||
export const GaugeComponent: FC<GaugeRenderProps> = memo(
|
||||
({ data, args, formatFactory, paletteService, chartsThemeService }) => {
|
||||
({ data, args, uiState, formatFactory, paletteService, chartsThemeService }) => {
|
||||
const {
|
||||
shape: gaugeType,
|
||||
palette,
|
||||
|
@ -230,6 +246,34 @@ export const GaugeComponent: FC<GaugeRenderProps> = memo(
|
|||
[paletteService]
|
||||
);
|
||||
|
||||
// Legacy chart was not formatting numbers, when was forming overrideColors.
|
||||
// To support the behavior of the color overriding, it is required to skip all the formatting, except percent.
|
||||
const overrideColor = useCallback(
|
||||
(value: number, bands: number[], formatter?: FieldFormat) => {
|
||||
const overrideColors = uiState?.get('vis.colors') ?? {};
|
||||
const valueIndex = bands.findIndex((band, index, allBands) => {
|
||||
if (index === allBands.length - 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return value >= band && value < allBands[index + 1];
|
||||
});
|
||||
|
||||
if (valueIndex < 0 || valueIndex === bands.length - 1) {
|
||||
return undefined;
|
||||
}
|
||||
const curValue = bands[valueIndex];
|
||||
const nextValue = bands[valueIndex + 1];
|
||||
|
||||
return overrideColors[
|
||||
`${formatter?.convert(curValue) ?? curValue} - ${
|
||||
formatter?.convert(nextValue) ?? nextValue
|
||||
}`
|
||||
];
|
||||
},
|
||||
[uiState]
|
||||
);
|
||||
|
||||
const table = data;
|
||||
const accessors = getAccessorsFromArgs(args, table.columns);
|
||||
|
||||
|
@ -353,12 +397,16 @@ export const GaugeComponent: FC<GaugeRenderProps> = memo(
|
|||
bandFillColor={
|
||||
colorMode === GaugeColorModes.PALETTE
|
||||
? (val) => {
|
||||
// bands value is equal to the stop. The purpose of this value is coloring the previous section, which is smaller, then the band.
|
||||
// So, the smaller value should be taken. For the first element -1, for the next - middle value of the previous section.
|
||||
let value = val.value - 1;
|
||||
const valueIndex = bands.indexOf(val.value);
|
||||
if (valueIndex > 0) {
|
||||
value = val.value - (bands[valueIndex] - bands[valueIndex - 1]) / 2;
|
||||
const value = getPreviousSectionValue(val.value, bands);
|
||||
|
||||
const overridedColor = overrideColor(
|
||||
value,
|
||||
args.percentageMode ? bands : args.palette?.params?.stops ?? [],
|
||||
args.percentageMode ? tickFormatter : undefined
|
||||
);
|
||||
|
||||
if (overridedColor) {
|
||||
return overridedColor;
|
||||
}
|
||||
|
||||
return args.palette
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
import { i18n } from '@kbn/i18n';
|
||||
import React from 'react';
|
||||
import { render, unmountComponentAtNode } from 'react-dom';
|
||||
import { PersistedState } from '../../../../visualizations/public';
|
||||
import { ThemeServiceStart } from '../../../../../core/public';
|
||||
import { KibanaThemeProvider } from '../../../../kibana_react/public';
|
||||
import { ExpressionRenderDefinition } from '../../../../expressions/common/expression_renderers';
|
||||
|
@ -40,6 +41,7 @@ export const gaugeRenderer: (
|
|||
formatFactory={getFormatService().deserialize}
|
||||
chartsThemeService={getThemeService()}
|
||||
paletteService={getPaletteService()}
|
||||
uiState={handlers.uiState as PersistedState}
|
||||
/>
|
||||
</div>
|
||||
</KibanaThemeProvider>,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue