mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 09:19:04 -04:00
[Lens] Threshold: set default color for new thresholds (#113008)
* 💄 Make dark grey default threshold color * ✅ Fix test * 👌 Integrate feedback * 👌 Fix bug * 👌 Filter threshold layers for color assignments * 👌 Small refactor * 🐛 Fix merging conflicts Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
fd0648daab
commit
218deff1cb
7 changed files with 41 additions and 52 deletions
|
@ -8,9 +8,10 @@
|
|||
import { uniq, mapValues } from 'lodash';
|
||||
import type { PaletteOutput, PaletteRegistry } from 'src/plugins/charts/public';
|
||||
import type { Datatable } from 'src/plugins/expressions';
|
||||
import { euiLightVars } from '@kbn/ui-shared-deps-src/theme';
|
||||
import type { AccessorConfig, FramePublicAPI } from '../types';
|
||||
import { getColumnToLabelMap } from './state_helpers';
|
||||
import type { FormatFactory } from '../../common';
|
||||
import { FormatFactory, LayerType, layerTypes } from '../../common';
|
||||
import type { XYLayerConfig } from '../../common/expressions';
|
||||
|
||||
const isPrimitive = (value: unknown): boolean => value != null && typeof value !== 'object';
|
||||
|
@ -20,8 +21,11 @@ interface LayerColorConfig {
|
|||
splitAccessor?: string;
|
||||
accessors: string[];
|
||||
layerId: string;
|
||||
layerType: LayerType;
|
||||
}
|
||||
|
||||
export const defaultThresholdColor = euiLightVars.euiColorDarkShade;
|
||||
|
||||
export type ColorAssignments = Record<
|
||||
string,
|
||||
{
|
||||
|
@ -37,13 +41,15 @@ export function getColorAssignments(
|
|||
): ColorAssignments {
|
||||
const layersPerPalette: Record<string, LayerColorConfig[]> = {};
|
||||
|
||||
layers.forEach((layer) => {
|
||||
const palette = layer.palette?.name || 'default';
|
||||
if (!layersPerPalette[palette]) {
|
||||
layersPerPalette[palette] = [];
|
||||
}
|
||||
layersPerPalette[palette].push(layer);
|
||||
});
|
||||
layers
|
||||
.filter(({ layerType }) => layerType === layerTypes.DATA)
|
||||
.forEach((layer) => {
|
||||
const palette = layer.palette?.name || 'default';
|
||||
if (!layersPerPalette[palette]) {
|
||||
layersPerPalette[palette] = [];
|
||||
}
|
||||
layersPerPalette[palette].push(layer);
|
||||
});
|
||||
|
||||
return mapValues(layersPerPalette, (paletteLayers) => {
|
||||
const seriesPerLayer = paletteLayers.map((layer, layerIndex) => {
|
||||
|
@ -111,6 +117,13 @@ export function getAccessorColorConfig(
|
|||
triggerIcon: 'disabled',
|
||||
};
|
||||
}
|
||||
if (layer.layerType === layerTypes.THRESHOLD) {
|
||||
return {
|
||||
columnId: accessor as string,
|
||||
triggerIcon: 'color',
|
||||
color: currentYConfig?.color || defaultThresholdColor,
|
||||
};
|
||||
}
|
||||
const columnToLabel = getColumnToLabelMap(layer, frame.datasourceLayers[layer.layerId]);
|
||||
const rank = colorAssignments[currentPalette.name].getRank(
|
||||
layer,
|
||||
|
@ -133,7 +146,7 @@ export function getAccessorColorConfig(
|
|||
return {
|
||||
columnId: accessor as string,
|
||||
triggerIcon: customColor ? 'color' : 'disabled',
|
||||
color: customColor ? customColor : undefined,
|
||||
color: customColor ?? undefined,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
|
|
@ -836,7 +836,6 @@ export function XYChart({
|
|||
<ThresholdAnnotations
|
||||
thresholdLayers={thresholdLayers}
|
||||
data={data}
|
||||
colorAssignments={colorAssignments}
|
||||
syncColors={syncColors}
|
||||
paletteService={paletteService}
|
||||
formatters={{
|
||||
|
|
|
@ -9,23 +9,21 @@ import React from 'react';
|
|||
import { groupBy } from 'lodash';
|
||||
import { EuiIcon } from '@elastic/eui';
|
||||
import { RectAnnotation, AnnotationDomainType, LineAnnotation } from '@elastic/charts';
|
||||
import type { PaletteRegistry, SeriesLayer } from 'src/plugins/charts/public';
|
||||
import type { PaletteRegistry } from 'src/plugins/charts/public';
|
||||
import type { FieldFormat } from 'src/plugins/field_formats/common';
|
||||
import { euiLightVars } from '@kbn/ui-shared-deps-src/theme';
|
||||
import type { LayerArgs } from '../../common/expressions';
|
||||
import type { LensMultiTable } from '../../common/types';
|
||||
import type { ColorAssignments } from './color_assignment';
|
||||
|
||||
export const ThresholdAnnotations = ({
|
||||
thresholdLayers,
|
||||
data,
|
||||
colorAssignments,
|
||||
formatters,
|
||||
paletteService,
|
||||
syncColors,
|
||||
}: {
|
||||
thresholdLayers: LayerArgs[];
|
||||
data: LensMultiTable;
|
||||
colorAssignments: ColorAssignments;
|
||||
formatters: Record<'left' | 'right' | 'bottom', FieldFormat | undefined>;
|
||||
paletteService: PaletteRegistry;
|
||||
syncColors: boolean;
|
||||
|
@ -36,12 +34,11 @@ export const ThresholdAnnotations = ({
|
|||
if (!thresholdLayer.yConfig) {
|
||||
return [];
|
||||
}
|
||||
const { columnToLabel, palette, yConfig: yConfigs, layerId } = thresholdLayer;
|
||||
const { columnToLabel, yConfig: yConfigs, layerId } = thresholdLayer;
|
||||
const columnToLabelMap: Record<string, string> = columnToLabel
|
||||
? JSON.parse(columnToLabel)
|
||||
: {};
|
||||
const table = data.tables[layerId];
|
||||
const colorAssignment = colorAssignments[palette.name];
|
||||
|
||||
const row = table.rows[0];
|
||||
|
||||
|
@ -62,27 +59,7 @@ export const ThresholdAnnotations = ({
|
|||
|
||||
const formatter = formatters[groupId || 'bottom'];
|
||||
|
||||
const seriesLayers: SeriesLayer[] = [
|
||||
{
|
||||
name: columnToLabelMap[yConfig.forAccessor],
|
||||
totalSeriesAtDepth: colorAssignment.totalSeriesCount,
|
||||
rankAtDepth: colorAssignment.getRank(
|
||||
thresholdLayer,
|
||||
String(yConfig.forAccessor),
|
||||
String(yConfig.forAccessor)
|
||||
),
|
||||
},
|
||||
];
|
||||
const defaultColor = paletteService.get(palette.name).getCategoricalColor(
|
||||
seriesLayers,
|
||||
{
|
||||
maxDepth: 1,
|
||||
behindText: false,
|
||||
totalSeries: colorAssignment.totalSeriesCount,
|
||||
syncColors,
|
||||
},
|
||||
palette.params
|
||||
);
|
||||
const defaultColor = euiLightVars.euiColorDarkShade;
|
||||
|
||||
const props = {
|
||||
groupId,
|
||||
|
@ -99,7 +76,7 @@ export const ThresholdAnnotations = ({
|
|||
|
||||
const sharedStyle = {
|
||||
strokeWidth: yConfig.lineWidth || 1,
|
||||
stroke: (yConfig.color || defaultColor) ?? '#f00',
|
||||
stroke: yConfig.color || defaultColor,
|
||||
dash: dashStyle,
|
||||
};
|
||||
|
||||
|
@ -179,7 +156,7 @@ export const ThresholdAnnotations = ({
|
|||
})}
|
||||
style={{
|
||||
...sharedStyle,
|
||||
fill: (yConfig.color || defaultColor) ?? '#f00',
|
||||
fill: yConfig.color || defaultColor,
|
||||
opacity: 0.1,
|
||||
}}
|
||||
/>
|
||||
|
|
|
@ -13,6 +13,7 @@ import { OperationMetadata, DatasourcePublicAPI } from '../types';
|
|||
import { getColumnToLabelMap } from './state_helpers';
|
||||
import type { ValidLayer, XYLayerConfig } from '../../common/expressions';
|
||||
import { layerTypes } from '../../common';
|
||||
import { defaultThresholdColor } from './color_assignment';
|
||||
|
||||
export const getSortedAccessors = (datasource: DatasourcePublicAPI, layer: XYLayerConfig) => {
|
||||
const originalOrder = datasource
|
||||
|
@ -334,9 +335,9 @@ export const buildExpression = (
|
|||
arguments: {
|
||||
forAccessor: [yConfig.forAccessor],
|
||||
axisMode: yConfig.axisMode ? [yConfig.axisMode] : [],
|
||||
color: yConfig.color ? [yConfig.color] : [],
|
||||
lineStyle: yConfig.lineStyle ? [yConfig.lineStyle] : [],
|
||||
lineWidth: yConfig.lineWidth ? [yConfig.lineWidth] : [],
|
||||
color: [yConfig.color || defaultThresholdColor],
|
||||
lineStyle: [yConfig.lineStyle || 'solid'],
|
||||
lineWidth: [yConfig.lineWidth || 1],
|
||||
fill: [yConfig.fill || 'none'],
|
||||
icon: yConfig.icon ? [yConfig.icon] : [],
|
||||
},
|
||||
|
|
|
@ -347,9 +347,6 @@ describe('xy_visualization', () => {
|
|||
{
|
||||
axisMode: 'bottom',
|
||||
forAccessor: 'newCol',
|
||||
icon: undefined,
|
||||
lineStyle: 'solid',
|
||||
lineWidth: 1,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
|
|
@ -448,12 +448,7 @@ export const getXyVisualization = ({
|
|||
if (!hasYConfig) {
|
||||
newLayer.yConfig = [
|
||||
...(newLayer.yConfig || []),
|
||||
// TODO: move this
|
||||
// add a default config if none is available
|
||||
{
|
||||
icon: undefined,
|
||||
lineStyle: 'solid',
|
||||
lineWidth: 1,
|
||||
// override with previous styling,
|
||||
...previousYConfig,
|
||||
// but keep the new group & id config
|
||||
|
|
|
@ -13,9 +13,13 @@ import { EuiFormRow, EuiColorPicker, EuiColorPickerProps, EuiToolTip, EuiIcon }
|
|||
import type { PaletteRegistry } from 'src/plugins/charts/public';
|
||||
import type { VisualizationDimensionEditorProps } from '../../types';
|
||||
import { State } from '../types';
|
||||
import { FormatFactory } from '../../../common';
|
||||
import { FormatFactory, layerTypes } from '../../../common';
|
||||
import { getSeriesColor } from '../state_helpers';
|
||||
import { getAccessorColorConfig, getColorAssignments } from '../color_assignment';
|
||||
import {
|
||||
defaultThresholdColor,
|
||||
getAccessorColorConfig,
|
||||
getColorAssignments,
|
||||
} from '../color_assignment';
|
||||
import { getSortedAccessors } from '../to_expression';
|
||||
import { updateLayer } from '.';
|
||||
import { TooltipWrapper } from '../../shared_components';
|
||||
|
@ -56,6 +60,9 @@ export const ColorPicker = ({
|
|||
const overwriteColor = getSeriesColor(layer, accessor);
|
||||
const currentColor = useMemo(() => {
|
||||
if (overwriteColor || !frame.activeData) return overwriteColor;
|
||||
if (layer.layerType === layerTypes.THRESHOLD) {
|
||||
return defaultThresholdColor;
|
||||
}
|
||||
|
||||
const datasource = frame.datasourceLayers[layer.layerId];
|
||||
const sortedAccessors: string[] = getSortedAccessors(datasource, layer);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue